diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 0c358042d1b56..97a1eed719c84 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -649,7 +649,7 @@ TSAN_INTERCEPTOR(void, siglongjmp_symname, uptr *env, int val) { REAL(siglongjmp_symname)(env, val); } -#if SANITIZER_NETBSD +#if SANITIZER_NETBSD || SANITIZER_APPLE TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) { { SCOPED_INTERCEPTOR_RAW(_longjmp, env, val); diff --git a/compiler-rt/test/tsan/setjmp_longjmp.c b/compiler-rt/test/tsan/setjmp_longjmp.c new file mode 100644 index 0000000000000..ed4d4c9200ec5 --- /dev/null +++ b/compiler-rt/test/tsan/setjmp_longjmp.c @@ -0,0 +1,55 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %deflake %run %t | FileCheck %s +// +// XFAIL: {{.*linux.*}} + +#include +#include +#include +#include + +int globalVar; + +void foo(jmp_buf *buf, char willExit) { + if (willExit) + globalVar = 1; + _longjmp(*buf, 1); +} + +void func2() { + jmp_buf buf; + const int reps = 1000; + for (int i = 0; i < reps; i++) { + if (_setjmp(buf) == 0) { + foo(&buf, i == reps - 1); + } + } +} + +void *writeGlobal(void *ctx) { + func2(); + return NULL; +} + +void *readGlobal(void *ctx) { + sleep(1); + printf("globalVar: %d\n", globalVar); + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, writeGlobal, NULL); + pthread_create(&t[1], NULL, readGlobal, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Read of size 4 at {{.*}} by thread +// CHECK: #0 readGlobal +// CHECK: Previous write of size 4 at {{.*}} by thread +// CHECK: #0 foo +// CHECK: #1 func2 +// CHECK: #2 writeGlobal