[compiler-rt] 82de586 - tsan: intercept clone
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 11 09:55:59 PST 2021
Author: Dmitry Vyukov
Date: 2021-11-11T18:55:54+01:00
New Revision: 82de586d4bd7c6a97f5bd30f1eaaa2e326c31612
URL: https://github.com/llvm/llvm-project/commit/82de586d4bd7c6a97f5bd30f1eaaa2e326c31612
DIFF: https://github.com/llvm/llvm-project/commit/82de586d4bd7c6a97f5bd30f1eaaa2e326c31612.diff
LOG: tsan: intercept clone
gtest uses clone for death tests and it needs the same
handling as fork to prevent deadlock (take runtime mutexes
before and release them after).
Reviewed By: melver
Differential Revision: https://reviews.llvm.org/D113677
Added:
compiler-rt/test/tsan/clone_deadlock.cpp
Modified:
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 617eda6503175..a712a3ad5bd9c 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -2210,6 +2210,30 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {
return WRAP(fork)(fake);
}
+TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
+ void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
+ SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
+ child_tid);
+ struct Arg {
+ int (*fn)(void *);
+ void *arg;
+ };
+ auto wrapper = +[](void *p) -> int {
+ auto *thr = cur_thread();
+ uptr pc = GET_CURRENT_PC();
+ ForkChildAfter(thr, pc);
+ FdOnFork(thr, pc);
+ auto *arg = static_cast<Arg *>(p);
+ return arg->fn(arg->arg);
+ };
+ ForkBefore(thr, pc);
+ Arg arg_wrapper = {fn, arg};
+ int pid = REAL(clone)(wrapper, stack, flags, &arg_wrapper, parent_tid, tls,
+ child_tid);
+ ForkParentAfter(thr, pc);
+ return pid;
+}
+
#if !SANITIZER_MAC && !SANITIZER_ANDROID
typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size,
void *data);
@@ -2841,6 +2865,7 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(fork);
TSAN_INTERCEPT(vfork);
+ TSAN_INTERCEPT(clone);
#if !SANITIZER_ANDROID
TSAN_INTERCEPT(dl_iterate_phdr);
#endif
diff --git a/compiler-rt/test/tsan/clone_deadlock.cpp b/compiler-rt/test/tsan/clone_deadlock.cpp
new file mode 100644
index 0000000000000..317ccdabdb704
--- /dev/null
+++ b/compiler-rt/test/tsan/clone_deadlock.cpp
@@ -0,0 +1,40 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=0 %run %t 2>&1 | FileCheck %s
+#include "test.h"
+#include <errno.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+long counter;
+
+static void *incrementer(void *arg) {
+ for (;;)
+ __sync_fetch_and_add(&counter, 1);
+ return 0;
+}
+
+static int cloned(void *arg) {
+ for (int i = 0; i < 1000; i++)
+ __sync_fetch_and_add(&counter, 1);
+ exit(0);
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t th;
+ pthread_create(&th, 0, incrementer, 0);
+ for (int i = 0; i < 100; i++) {
+ char stack[64 << 10] __attribute__((aligned(64)));
+ int pid = clone(cloned, stack + sizeof(stack), SIGCHLD, 0);
+ if (pid == -1) {
+ fprintf(stderr, "failed to clone: %d\n", errno);
+ exit(1);
+ }
+ while (wait(0) != pid) {
+ }
+ }
+ fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE
More information about the llvm-commits
mailing list