[compiler-rt] r177647 - tsan: better reporting of thread leaks

Dmitry Vyukov dvyukov at google.com
Thu Mar 21 09:55:18 PDT 2013


Author: dvyukov
Date: Thu Mar 21 11:55:17 2013
New Revision: 177647

URL: http://llvm.org/viewvc/llvm-project?rev=177647&view=rev
Log:
tsan: better reporting of thread leaks
1. do not report running threads as leaks
2. aggregate leaked threads by creation stack


Added:
    compiler-rt/trunk/lib/tsan/lit_tests/thread_leak4.c
    compiler-rt/trunk/lib/tsan/lit_tests/thread_leak5.c
Modified:
    compiler-rt/trunk/lib/tsan/lit_tests/thread_leak3.c
    compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc

Modified: compiler-rt/trunk/lib/tsan/lit_tests/thread_leak3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/thread_leak3.c?rev=177647&r1=177646&r2=177647&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/thread_leak3.c (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/thread_leak3.c Thu Mar 21 11:55:17 2013
@@ -1,5 +1,6 @@
 // RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
 #include <pthread.h>
+#include <unistd.h>
 
 void *Thread(void *x) {
   return 0;
@@ -8,6 +9,7 @@ void *Thread(void *x) {
 int main() {
   pthread_t t;
   pthread_create(&t, 0, Thread, 0);
+  sleep(1);
   return 0;
 }
 

Added: compiler-rt/trunk/lib/tsan/lit_tests/thread_leak4.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/thread_leak4.c?rev=177647&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/thread_leak4.c (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/thread_leak4.c Thu Mar 21 11:55:17 2013
@@ -0,0 +1,16 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <unistd.h>
+
+void *Thread(void *x) {
+  sleep(10);
+  return 0;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, 0, Thread, 0);
+  return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak

Added: compiler-rt/trunk/lib/tsan/lit_tests/thread_leak5.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/thread_leak5.c?rev=177647&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/thread_leak5.c (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/thread_leak5.c Thu Mar 21 11:55:17 2013
@@ -0,0 +1,19 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <unistd.h>
+
+void *Thread(void *x) {
+  return 0;
+}
+
+int main() {
+  for (int i = 0; i < 5; i++) {
+    pthread_t t;
+    pthread_create(&t, 0, Thread, 0);
+  }
+  sleep(1);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: thread leak
+// CHECK:   And 4 more similar thread leaks

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc?rev=177647&r1=177646&r2=177647&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Thu Mar 21 11:55:17 2013
@@ -22,7 +22,8 @@ ReportDesc::ReportDesc()
     , locs(MBlockReportLoc)
     , mutexes(MBlockReportMutex)
     , threads(MBlockReportThread)
-    , sleep() {
+    , sleep()
+    , count() {
 }
 
 ReportMop::ReportMop()
@@ -201,6 +202,9 @@ void PrintReport(const ReportDesc *rep)
   for (uptr i = 0; i < rep->threads.Size(); i++)
     PrintThread(rep->threads[i]);
 
+  if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
+    Printf("  And %d more similar thread leaks.\n\n", rep->count - 1);
+
   if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep)))
     ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func);
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.h?rev=177647&r1=177646&r2=177647&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Thu Mar 21 11:55:17 2013
@@ -102,6 +102,7 @@ class ReportDesc {
   Vector<ReportMutex*> mutexes;
   Vector<ReportThread*> threads;
   ReportStack *sleep;
+  int count;
 
   ReportDesc();
   ~ReportDesc();

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=177647&r1=177646&r2=177647&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Thu Mar 21 11:55:17 2013
@@ -554,6 +554,7 @@ class ScopedReport {
   void AddMutex(const SyncVar *s);
   void AddLocation(uptr addr, uptr size);
   void AddSleep(u32 stack_id);
+  void SetCount(int count);
 
   const ReportDesc *GetReport() const;
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=177647&r1=177646&r2=177647&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Thu Mar 21 11:55:17 2013
@@ -365,6 +365,10 @@ void ScopedReport::AddSleep(u32 stack_id
 }
 #endif
 
+void ScopedReport::SetCount(int count) {
+  rep_->count = count;
+}
+
 const ReportDesc *ScopedReport::GetReport() const {
   return rep_;
 }

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=177647&r1=177646&r2=177647&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Thu Mar 21 11:55:17 2013
@@ -143,26 +143,44 @@ void ThreadContext::OnFinished() {
   thr = 0;
 }
 
-static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *unused) {
+#ifndef TSAN_GO
+struct ThreadLeak {
+  ThreadContext *tctx;
+  int count;
+};
+
+static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
+  Vector<ThreadLeak> &leaks = *(Vector<ThreadLeak>*)arg;
   ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
-  if (tctx->detached)
-    return;
-  if (tctx->status != ThreadStatusCreated
-      && tctx->status != ThreadStatusRunning
-      && tctx->status != ThreadStatusFinished)
+  if (tctx->detached || tctx->status != ThreadStatusFinished)
     return;
-  ScopedReport rep(ReportTypeThreadLeak);
-  rep.AddThread(tctx);
-  OutputReport(CTX(), rep);
+  for (uptr i = 0; i < leaks.Size(); i++) {
+    if (leaks[i].tctx->creation_stack_id == tctx->creation_stack_id) {
+      leaks[i].count++;
+      return;
+    }
+  }
+  ThreadLeak leak = {tctx, 1};
+  leaks.PushBack(leak);
 }
+#endif
 
 void ThreadFinalize(ThreadState *thr) {
   CHECK_GT(thr->in_rtl, 0);
+#ifndef TSAN_GO
   if (!flags()->report_thread_leaks)
     return;
   ThreadRegistryLock l(CTX()->thread_registry);
+  Vector<ThreadLeak> leaks(MBlockScopedBuf);
   CTX()->thread_registry->RunCallbackForEachThreadLocked(
-      MaybeReportThreadLeak, 0);
+      MaybeReportThreadLeak, &leaks);
+  for (uptr i = 0; i < leaks.Size(); i++) {
+    ScopedReport rep(ReportTypeThreadLeak);
+    rep.AddThread(leaks[i].tctx);
+    rep.SetCount(leaks[i].count);
+    OutputReport(CTX(), rep);
+  }
+#endif
 }
 
 int ThreadCount(ThreadState *thr) {





More information about the llvm-commits mailing list