From: Vitaly Buka Date: Wed, 9 May 2018 23:02:14 +0000 (+0000) Subject: [lsan] Report unsuspended threads X-Git-Tag: llvmorg-7.0.0-rc1~6386 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ed43f18b55a1fdf30d73a1c08b273177774fdeee;p=platform%2Fupstream%2Fllvm.git [lsan] Report unsuspended threads Summary: Leak checker needs to suspend all process threads. If we have some running thread in registry but not suspended we can have false leak report. So we will report this case here for future debugging. Reviewers: eugenis Subscribers: kubamracek, llvm-commits Differential Revision: https://reviews.llvm.org/D46663 llvm-svn: 331936 --- diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index ad81512..4a8779f 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -477,6 +477,11 @@ void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); } +ThreadRegistry *GetThreadRegistryLocked() { + __asan::asanThreadRegistry().CheckLocked(); + return &__asan::asanThreadRegistry(); +} + void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); } diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index bdc825d..eaa5cad 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -15,14 +15,15 @@ #include "lsan_common.h" #include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_procmaps.h" +#include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_suppressions.h" -#include "sanitizer_common/sanitizer_report_decorator.h" +#include "sanitizer_common/sanitizer_thread_registry.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" #if CAN_SANITIZE_LEAKS @@ -526,11 +527,36 @@ struct CheckForLeaksParam { LeakReport leak_report; }; +static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) { + const InternalMmapVector &suspended_threads = + *(const InternalMmapVector *)arg; + if (tctx->status == ThreadStatusRunning) { + uptr i = InternalLowerBound(suspended_threads, 0, suspended_threads.size(), + tctx->os_id, CompareLess()); + if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id) + Report("Running thread %d was not suspended. False leaks are possible.\n", + tctx->os_id); + }; +} + +static void ReportUnsuspendedThreads( + const SuspendedThreadsList &suspended_threads) { + InternalMmapVector threads(suspended_threads.ThreadCount()); + for (uptr i = 0; i < suspended_threads.ThreadCount(); ++i) + threads[i] = suspended_threads.GetThreadID(i); + + Sort(threads.data(), threads.size()); + + GetThreadRegistryLocked()->RunCallbackForEachThreadLocked( + &ReportIfNotSuspended, &threads); +} + static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads, void *arg) { CheckForLeaksParam *param = reinterpret_cast(arg); CHECK(param); CHECK(!param->success); + ReportUnsuspendedThreads(suspended_threads); ClassifyAllChunks(suspended_threads); ForEachChunk(CollectLeaksCb, ¶m->leak_report); // Clean up for subsequent leak checks. This assumes we did not overwrite any diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index 2bffed4..1d1e1e4 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -47,6 +47,7 @@ namespace __sanitizer { class FlagParser; +class ThreadRegistry; struct DTLS; } @@ -204,6 +205,7 @@ bool WordIsPoisoned(uptr addr); // Wrappers for ThreadRegistry access. void LockThreadRegistry(); void UnlockThreadRegistry(); +ThreadRegistry *GetThreadRegistryLocked(); bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, uptr *tls_begin, uptr *tls_end, uptr *cache_begin, uptr *cache_end, DTLS **dtls); diff --git a/compiler-rt/lib/lsan/lsan_thread.cc b/compiler-rt/lib/lsan/lsan_thread.cc index 4404c8c..a25aff3 100644 --- a/compiler-rt/lib/lsan/lsan_thread.cc +++ b/compiler-rt/lib/lsan/lsan_thread.cc @@ -155,4 +155,9 @@ void UnlockThreadRegistry() { thread_registry->Unlock(); } +ThreadRegistry *GetThreadRegistryLocked() { + thread_registry->CheckLocked(); + return thread_registry; +} + } // namespace __lsan