diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp index 52d7eff7281e3..335de3383db01 100644 --- a/compiler-rt/lib/asan/asan_allocator.cpp +++ b/compiler-rt/lib/asan/asan_allocator.cpp @@ -1153,33 +1153,6 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) { return kIgnoreObjectSuccess; } -void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) { - // Look for the arg pointer of threads that have been created or are running. - // This is necessary to prevent false positive leaks due to the AsanThread - // holding the only live reference to a heap object. This can happen because - // the `pthread_create()` interceptor doesn't wait for the child thread to - // start before returning and thus loosing the the only live reference to the - // heap object on the stack. - - __asan::AsanThreadContext *atctx = - reinterpret_cast<__asan::AsanThreadContext *>(tctx); - __asan::AsanThread *asan_thread = atctx->thread; - - // Note ThreadStatusRunning is required because there is a small window where - // the thread status switches to `ThreadStatusRunning` but the `arg` pointer - // still isn't on the stack yet. - if (atctx->status != ThreadStatusCreated && - atctx->status != ThreadStatusRunning) - return; - - uptr thread_arg = reinterpret_cast(asan_thread->get_arg()); - if (!thread_arg) - return; - - auto ptrsVec = reinterpret_cast *>(ptrs); - ptrsVec->push_back(thread_arg); -} - } // namespace __lsan // ---------------------- Interface ---------------- {{{1 diff --git a/compiler-rt/lib/asan/asan_thread.cpp b/compiler-rt/lib/asan/asan_thread.cpp index 4b5e4a33fbdda..10a1e8c4abc1f 100644 --- a/compiler-rt/lib/asan/asan_thread.cpp +++ b/compiler-rt/lib/asan/asan_thread.cpp @@ -518,9 +518,41 @@ void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, fake_stack->ForEachFakeFrame(callback, arg); } -void RunCallbackForEachThreadLocked(__sanitizer::ThreadRegistry::ThreadCallback cb, - void *arg) { - GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(cb, arg); +static void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) { + // Look for the arg pointer of threads that have been created or are running. + // This is necessary to prevent false positive leaks due to the AsanThread + // holding the only live reference to a heap object. This can happen because + // the `pthread_create()` interceptor doesn't wait for the child thread to + // start before returning and thus loosing the the only live reference to the + // heap object on the stack. + + __asan::AsanThreadContext *atctx = + reinterpret_cast<__asan::AsanThreadContext *>(tctx); + __asan::AsanThread *asan_thread = atctx->thread; + + // Note ThreadStatusRunning is required because there is a small window where + // the thread status switches to `ThreadStatusRunning` but the `arg` pointer + // still isn't on the stack yet. + if (atctx->status != ThreadStatusCreated && + atctx->status != ThreadStatusRunning) + return; + + uptr thread_arg = reinterpret_cast(asan_thread->get_arg()); + if (!thread_arg) + return; + + auto ptrsVec = reinterpret_cast *>(ptrs); + ptrsVec->push_back(thread_arg); +} + +void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { + GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( + GetAdditionalThreadContextPtrs, ptrs); +} + +void ReportUnsuspendedThreadsLocked(InternalMmapVector *threads) { + GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( + &ReportIfNotSuspended, threads); } void FinishThreadLocked(u32 tid) { diff --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp index 43928ad294e2c..b18d829a1a2ae 100644 --- a/compiler-rt/lib/lsan/lsan_allocator.cpp +++ b/compiler-rt/lib/lsan/lsan_allocator.cpp @@ -319,7 +319,7 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) { } } -void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) { +void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { // This function can be used to treat memory reachable from `tctx` as live. // This is useful for threads that have been created but not yet started. diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 33c590cd40695..0fe20011150ef 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -371,7 +371,7 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_iterate_dynamic_tls( static void ProcessThreadRegistry(Frontier *frontier) { InternalMmapVector ptrs; - RunCallbackForEachThreadLocked(GetAdditionalThreadContextPtrs, &ptrs); + GetAdditionalThreadContextPtrsLocked(&ptrs); for (uptr i = 0; i < ptrs.size(); ++i) { void *ptr = reinterpret_cast(ptrs[i]); @@ -668,7 +668,7 @@ void LeakSuppressionContext::PrintMatchedSuppressions() { Printf("%s\n\n", line); } -static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) { +void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) { const InternalMmapVector &suspended_threads = *(const InternalMmapVector *)arg; if (tctx->status == ThreadStatusRunning) { @@ -695,8 +695,7 @@ static void ReportUnsuspendedThreads( threads[i] = suspended_threads.GetThreadID(i); Sort(threads.data(), threads.size()); - - RunCallbackForEachThreadLocked(&ReportIfNotSuspended, &threads); + ReportUnsuspendedThreadsLocked(&threads); } # endif // !SANITIZER_FUCHSIA diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index 089aa10155a0c..add916c665dc9 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -105,9 +105,9 @@ bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, void GetAllThreadAllocatorCachesLocked(InternalMmapVector *caches); void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, void *arg); - -void RunCallbackForEachThreadLocked(__sanitizer::ThreadRegistry::ThreadCallback cb, - void *arg); +void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs); +void ReportUnsuspendedThreadsLocked(InternalMmapVector *threads); +void FinishThreadLocked(u32 tid); //// -------------------------------------------------------------------------- //// Allocator prototypes. @@ -146,8 +146,6 @@ void ForEachChunk(ForEachChunkCallback callback, void *arg); // Helper for __lsan_ignore_object(). IgnoreObjectResult IgnoreObjectLocked(const void *p); -void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs); - // The rest of the LSan interface which is implemented by library. struct ScopedStopTheWorldLock { @@ -269,6 +267,7 @@ void DoLeakCheck(); void DoRecoverableLeakCheckVoid(); void DisableCounterUnderflow(); bool DisabledInThisThread(); +void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg); // Used to implement __lsan::ScopedDisabler. void DisableInThisThread(); diff --git a/compiler-rt/lib/lsan/lsan_fuchsia.cpp b/compiler-rt/lib/lsan/lsan_fuchsia.cpp index 1bcb748e7d2ae..03ac0afbabff7 100644 --- a/compiler-rt/lib/lsan/lsan_fuchsia.cpp +++ b/compiler-rt/lib/lsan/lsan_fuchsia.cpp @@ -68,7 +68,7 @@ void InitializeMainThread() { } void GetAllThreadAllocatorCachesLocked(InternalMmapVector *caches) { - RunCallbackForEachThreadLocked( + GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( [](ThreadContextBase *tctx, void *arg) { auto ctx = static_cast(tctx); static_cast(arg)->push_back(ctx->cache_begin()); diff --git a/compiler-rt/lib/lsan/lsan_thread.cpp b/compiler-rt/lib/lsan/lsan_thread.cpp index d04d9057b71be..02a873d5367a3 100644 --- a/compiler-rt/lib/lsan/lsan_thread.cpp +++ b/compiler-rt/lib/lsan/lsan_thread.cpp @@ -87,9 +87,9 @@ ThreadRegistry *GetLsanThreadRegistryLocked() { return thread_registry; } -void RunCallbackForEachThreadLocked( - __sanitizer::ThreadRegistry::ThreadCallback cb, void *arg) { - GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(cb, arg); +void ReportUnsuspendedThreadsLocked(InternalMmapVector *threads) { + GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( + &ReportIfNotSuspended, threads); } } // namespace __lsan