diff options
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 4 | ||||
| -rw-r--r-- | compiler-rt/test/tsan/fork_atexit.cc | 37 |
2 files changed, 40 insertions, 1 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 76cfd31d36a..b9f02b9d967 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -333,7 +333,9 @@ static AtExitContext *atexit_ctx; TSAN_INTERCEPTOR(int, atexit, void (*f)()) { if (cur_thread()->in_symbolizer) return 0; - SCOPED_TSAN_INTERCEPTOR(atexit, f); + // We want to setup the atexit callback even if we are in ignored lib + // or after fork. + SCOPED_INTERCEPTOR_RAW(atexit, f); return atexit_ctx->atexit(thr, pc, false, (void(*)())f, 0); } diff --git a/compiler-rt/test/tsan/fork_atexit.cc b/compiler-rt/test/tsan/fork_atexit.cc new file mode 100644 index 00000000000..1692b6cb56e --- /dev/null +++ b/compiler-rt/test/tsan/fork_atexit.cc @@ -0,0 +1,37 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="atexit_sleep_ms=50" %t 2>&1 | FileCheck %s +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +void foo() { + printf("CHILD ATEXIT\n"); +} + +void *worker(void *unused) { + return 0; +} + +int main() { + pthread_t t; + pthread_create(&t, NULL, worker, NULL); + int pid = fork(); + if (pid == 0) { + // child + atexit(foo); + fprintf(stderr, "CHILD DONE\n"); + } else { + pthread_join(t, 0); + if (waitpid(pid, 0, 0) == -1) { + perror("waitpid"); + exit(1); + } + fprintf(stderr, "PARENT DONE\n"); + } +} + +// CHECK: CHILD DONE +// CHECK: CHILD ATEXIT +// CHECK: PARENT DONE |

