From 303d278ad2fa9bb8caf5beaac7374ea0773dc2fe Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Thu, 19 Aug 2021 13:17:45 +0200 Subject: [PATCH] [tsan] Fix pthread_once() on Mac OS X Change 636428c727cd enabled BlockingRegion hooks for pthread_once(). Unfortunately this seems to cause crashes on Mac OS X which uses pthread_once() from locations that seem to result in crashes: | ThreadSanitizer:DEADLYSIGNAL | ==31465==ERROR: ThreadSanitizer: stack-overflow on address 0x7ffee73fffd8 (pc 0x00010807fd2a bp 0x7ffee7400050 sp 0x7ffee73fffb0 T93815) | #0 __tsan::MetaMap::GetSync(__tsan::ThreadState*, unsigned long, unsigned long, bool, bool) tsan_sync.cpp:195 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x78d2a) | #1 __tsan::MutexPreLock(__tsan::ThreadState*, unsigned long, unsigned long, unsigned int) tsan_rtl_mutex.cpp:143 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x6cefc) | #2 wrap_pthread_mutex_lock sanitizer_common_interceptors.inc:4240 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x3dae0) | #3 flockfile :2 (libsystem_c.dylib:x86_64+0x38a69) | #4 puts :2 (libsystem_c.dylib:x86_64+0x3f69b) | #5 wrap_puts sanitizer_common_interceptors.inc (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x34d83) | #6 __tsan::OnPotentiallyBlockingRegionBegin() cxa_guard_acquire.cpp:8 (foo:x86_64+0x100000e48) | #7 wrap_pthread_once tsan_interceptors_posix.cpp:1512 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2f6e6) From the stack trace it can be seen that the caller is unknown, and the resulting stack-overflow seems to indicate that whoever the caller is does not have enough stack space or otherwise is running in a limited environment not yet ready for full instrumentation. Fix it by reverting behaviour on Mac OS X to not call BlockingRegion hooks from pthread_once(). Reported-by: azharudd Reviewed By: glider Differential Revision: https://reviews.llvm.org/D108305 --- .../lib/tsan/rtl/tsan_interceptors_posix.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index af0073726765c..ec3a548f05aa4 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -855,9 +855,15 @@ constexpr u32 kGuardDone = 1; constexpr u32 kGuardRunning = 1 << 16; constexpr u32 kGuardWaiter = 1 << 17; -static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g) { - OnPotentiallyBlockingRegionBegin(); - auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd); +static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g, + bool blocking_hooks = true) { + if (blocking_hooks) + OnPotentiallyBlockingRegionBegin(); + auto on_exit = at_scope_exit([blocking_hooks] { + if (blocking_hooks) + OnPotentiallyBlockingRegionEnd(); + }); + for (;;) { u32 cmp = atomic_load(g, memory_order_acquire); if (cmp == kGuardInit) { @@ -1509,7 +1515,9 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { else a = static_cast(o); - if (guard_acquire(thr, pc, a)) { + // Mac OS X appears to use pthread_once() where calling BlockingRegion hooks + // result in crashes due to too little stack space. + if (guard_acquire(thr, pc, a, !SANITIZER_MAC)) { (*f)(); guard_release(thr, pc, a); }