[compiler-rt] r331936 - [lsan] Report unsuspended threads

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Wed May 9 16:02:14 PDT 2018


Author: vitalybuka
Date: Wed May  9 16:02:14 2018
New Revision: 331936

URL: http://llvm.org/viewvc/llvm-project?rev=331936&view=rev
Log:
[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

Modified:
    compiler-rt/trunk/lib/asan/asan_thread.cc
    compiler-rt/trunk/lib/lsan/lsan_common.cc
    compiler-rt/trunk/lib/lsan/lsan_common.h
    compiler-rt/trunk/lib/lsan/lsan_thread.cc

Modified: compiler-rt/trunk/lib/asan/asan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread.cc?rev=331936&r1=331935&r2=331936&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_thread.cc Wed May  9 16:02:14 2018
@@ -477,6 +477,11 @@ void UnlockThreadRegistry() {
   __asan::asanThreadRegistry().Unlock();
 }
 
+ThreadRegistry *GetThreadRegistryLocked() {
+  __asan::asanThreadRegistry().CheckLocked();
+  return &__asan::asanThreadRegistry();
+}
+
 void EnsureMainThreadIDIsCorrect() {
   __asan::EnsureMainThreadIDIsCorrect();
 }

Modified: compiler-rt/trunk/lib/lsan/lsan_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=331936&r1=331935&r2=331936&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc Wed May  9 16:02:14 2018
@@ -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<tid_t> &suspended_threads =
+      *(const InternalMmapVector<tid_t> *)arg;
+  if (tctx->status == ThreadStatusRunning) {
+    uptr i = InternalLowerBound(suspended_threads, 0, suspended_threads.size(),
+                                tctx->os_id, CompareLess<int>());
+    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<tid_t> 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<CheckForLeaksParam *>(arg);
   CHECK(param);
   CHECK(!param->success);
+  ReportUnsuspendedThreads(suspended_threads);
   ClassifyAllChunks(suspended_threads);
   ForEachChunk(CollectLeaksCb, &param->leak_report);
   // Clean up for subsequent leak checks. This assumes we did not overwrite any

Modified: compiler-rt/trunk/lib/lsan/lsan_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.h?rev=331936&r1=331935&r2=331936&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.h (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.h Wed May  9 16:02:14 2018
@@ -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);

Modified: compiler-rt/trunk/lib/lsan/lsan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_thread.cc?rev=331936&r1=331935&r2=331936&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_thread.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_thread.cc Wed May  9 16:02:14 2018
@@ -155,4 +155,9 @@ void UnlockThreadRegistry() {
   thread_registry->Unlock();
 }
 
+ThreadRegistry *GetThreadRegistryLocked() {
+  thread_registry->CheckLocked();
+  return thread_registry;
+}
+
 } // namespace __lsan




More information about the llvm-commits mailing list