From ebf63d0095ab60ea940e934c9cc0f62c5abd06b5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 21 Mar 2013 16:55:17 +0000 Subject: [PATCH] tsan: better reporting of thread leaks 1. do not report running threads as leaks 2. aggregate leaked threads by creation stack llvm-svn: 177647 --- compiler-rt/lib/tsan/lit_tests/thread_leak3.c | 2 ++ compiler-rt/lib/tsan/lit_tests/thread_leak4.c | 16 +++++++++++ compiler-rt/lib/tsan/lit_tests/thread_leak5.c | 19 ++++++++++++++ compiler-rt/lib/tsan/rtl/tsan_report.cc | 6 ++++- compiler-rt/lib/tsan/rtl/tsan_report.h | 1 + compiler-rt/lib/tsan/rtl/tsan_rtl.h | 1 + compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 4 +++ compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 38 ++++++++++++++++++++------- 8 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 compiler-rt/lib/tsan/lit_tests/thread_leak4.c create mode 100644 compiler-rt/lib/tsan/lit_tests/thread_leak5.c diff --git a/compiler-rt/lib/tsan/lit_tests/thread_leak3.c b/compiler-rt/lib/tsan/lit_tests/thread_leak3.c index a39c93c..3577164 100644 --- a/compiler-rt/lib/tsan/lit_tests/thread_leak3.c +++ b/compiler-rt/lib/tsan/lit_tests/thread_leak3.c @@ -1,5 +1,6 @@ // RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s #include +#include 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; } diff --git a/compiler-rt/lib/tsan/lit_tests/thread_leak4.c b/compiler-rt/lib/tsan/lit_tests/thread_leak4.c new file mode 100644 index 0000000..3909c0a --- /dev/null +++ b/compiler-rt/lib/tsan/lit_tests/thread_leak4.c @@ -0,0 +1,16 @@ +// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s +#include +#include + +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 diff --git a/compiler-rt/lib/tsan/lit_tests/thread_leak5.c b/compiler-rt/lib/tsan/lit_tests/thread_leak5.c new file mode 100644 index 0000000..fc72b14 --- /dev/null +++ b/compiler-rt/lib/tsan/lit_tests/thread_leak5.c @@ -0,0 +1,19 @@ +// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s +#include +#include + +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 diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc index 30e5488..bfa2660 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -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); diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h index eacb10c..b2ce0dd 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.h +++ b/compiler-rt/lib/tsan/rtl/tsan_report.h @@ -102,6 +102,7 @@ class ReportDesc { Vector mutexes; Vector threads; ReportStack *sleep; + int count; ReportDesc(); ~ReportDesc(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index c216a80..3af0402 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -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; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index 50c5311..fd61f4a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -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_; } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index e93a7a3..35e9787 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -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 &leaks = *(Vector*)arg; ThreadContext *tctx = static_cast(tctx_base); - if (tctx->detached) + if (tctx->detached || tctx->status != ThreadStatusFinished) return; - if (tctx->status != ThreadStatusCreated - && tctx->status != ThreadStatusRunning - && 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 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) { -- 2.7.4