summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc7
-rw-r--r--lib/sanitizer_common/sanitizer_common.h1
-rw-r--r--lib/tsan/go/tsan_go.cc6
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc8
-rw-r--r--lib/tsan/rtl/tsan_platform.h3
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc26
-rw-r--r--lib/tsan/rtl/tsan_rtl.h3
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;