diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -434,6 +434,9 @@ // Ensure thread-safety. BlockingMutexLock l(&interceptor_ctx()->atexit_mu); + // __cxa_atexit calls calloc. If we don't ignore interceptors, we will fail + // due to atexit_mu held on exit from the calloc interceptor. + ScopedIgnoreInterceptors ignore; res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0); // Push AtExitCtx on the top of the stack of callback functions diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp b/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp --- a/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp +++ b/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp @@ -48,6 +48,9 @@ } TEST(MetaMap, Sync) { + // EXPECT can call memset/etc. Disable interceptors to prevent + // them from detecting that we exit runtime with mutexes held. + ScopedIgnoreInterceptors ignore; ThreadState *thr = cur_thread(); MetaMap *m = &ctx->metamap; u64 block[4] = {}; // fake malloc block @@ -71,6 +74,7 @@ } TEST(MetaMap, MoveMemory) { + ScopedIgnoreInterceptors ignore; ThreadState *thr = cur_thread(); MetaMap *m = &ctx->metamap; u64 block1[4] = {}; // fake malloc block @@ -108,6 +112,7 @@ } TEST(MetaMap, ResetSync) { + ScopedIgnoreInterceptors ignore; ThreadState *thr = cur_thread(); MetaMap *m = &ctx->metamap; u64 block[1] = {}; // fake malloc block