diff options
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.cc | 7 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 1 | ||||
-rw-r--r-- | lib/tsan/go/tsan_go.cc | 6 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cc | 8 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_platform.h | 3 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.cc | 26 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.h | 3 |
7 files changed, 46 insertions, 8 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 0eab82446..c0c7748a7 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -263,6 +263,11 @@ void DecreaseTotalMmap(uptr size) { atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed); } +static void (*sandboxing_callback)(); +void SetSandboxingCallback(void (*f)()) { + sandboxing_callback = f; +} + } // namespace __sanitizer using namespace __sanitizer; // NOLINT @@ -298,6 +303,8 @@ void __sanitizer_set_report_path(const char *path) { void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) { (void)reserved; PrepareForSandboxing(); + if (sandboxing_callback) + sandboxing_callback(); } void __sanitizer_report_error_summary(const char *error_summary) { diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 00c686ead..8fa41679f 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -184,6 +184,7 @@ bool StackSizeIsUnlimited(); void SetStackSizeLimitInBytes(uptr limit); void AdjustStackSize(void *attr); void PrepareForSandboxing(); +void SetSandboxingCallback(void (*f)()); void InitTlsSize(); uptr GetTlsSize(); diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc index 3f1685727..e7761fee3 100644 --- a/lib/tsan/go/tsan_go.cc +++ b/lib/tsan/go/tsan_go.cc @@ -28,7 +28,11 @@ bool IsExpectedReport(uptr addr, uptr size) { return false; } -void internal_start_thread(void(*func)(void*), void *arg) { +void *internal_start_thread(void(*func)(void*), void *arg) { + return 0; +} + +void internal_join_thread(void *th) { } ReportLocation *SymbolizeData(uptr addr) { diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index b9f02b9d9..b545f8c52 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -2473,15 +2473,19 @@ void InitializeInterceptors() { FdInit(); } -void internal_start_thread(void(*func)(void *arg), void *arg) { +void *internal_start_thread(void(*func)(void *arg), void *arg) { // Start the thread with signals blocked, otherwise it can steal user signals. __sanitizer_sigset_t set, old; internal_sigfillset(&set); internal_sigprocmask(SIG_SETMASK, &set, &old); void *th; REAL(pthread_create)(&th, 0, (void*(*)(void *arg))func, arg); - REAL(pthread_detach)(th); internal_sigprocmask(SIG_SETMASK, &old, 0); + return th; +} + +void internal_join_thread(void *th) { + REAL(pthread_join)(th, 0); } } // namespace __tsan diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index e960d5d99..7abe5f0d7 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -164,7 +164,8 @@ uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { return p; } -void internal_start_thread(void(*func)(void*), void *arg); +void *internal_start_thread(void(*func)(void*), void *arg); +void internal_join_thread(void *th); // Says whether the addr relates to a global var. // Guesses with high probability, may yield both false positives and negatives. diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index b0ae2dd59..33b9f0bc2 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -120,8 +120,13 @@ static void MemoryProfiler(Context *ctx, fd_t fd, int i) { } static void BackgroundThread(void *arg) { +#ifndef TSAN_GO // This is a non-initialized non-user thread, nothing to see here. - ScopedIgnoreInterceptors ignore; + // We don't use ScopedIgnoreInterceptors, because we want ignores to be + // enabled even when the thread function exits (e.g. during pthread thread + // shutdown code). + cur_thread()->ignore_interceptors++; +#endif const u64 kMs2Ns = 1000 * 1000; fd_t mprof_fd = kInvalidFd; @@ -140,8 +145,10 @@ static void BackgroundThread(void *arg) { u64 last_flush = NanoTime(); uptr last_rss = 0; - for (int i = 0; ; i++) { - SleepForSeconds(1); + for (int i = 0; + atomic_load(&ctx->stop_background_thread, memory_order_relaxed) == 0; + i++) { + SleepForMillis(100); u64 now = NanoTime(); // Flush memory if requested. @@ -192,6 +199,16 @@ static void BackgroundThread(void *arg) { } } +static void StartBackgroundThread() { + ctx->background_thread = internal_start_thread(&BackgroundThread, 0); +} + +static void StopBackgroundThread() { + atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed); + internal_join_thread(ctx->background_thread); + ctx->background_thread = 0; +} + void DontNeedShadowFor(uptr addr, uptr size) { uptr shadow_beg = MemToShadow(addr); uptr shadow_end = MemToShadow(addr + size); @@ -250,7 +267,8 @@ void Initialize(ThreadState *thr) { Symbolizer::Init(common_flags()->external_symbolizer_path); Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer); #endif - internal_start_thread(&BackgroundThread, 0); + StartBackgroundThread(); + SetSandboxingCallback(StopBackgroundThread); if (flags()->detect_deadlocks) ctx->dd = DDetector::Create(flags()); diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index f862e5213..c542bd2bc 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -536,6 +536,9 @@ struct Context { int nmissed_expected; atomic_uint64_t last_symbolize_time_ns; + void *background_thread; + atomic_uint32_t stop_background_thread; + ThreadRegistry *thread_registry; Vector<RacyStacks> racy_stacks; |