[compiler-rt] r207204 - tsan: better reports for "double lock of a mutex"

Dmitry Vyukov dvyukov at google.com
Fri Apr 25 00:42:55 PDT 2014


Author: dvyukov
Date: Fri Apr 25 02:42:55 2014
New Revision: 207204

URL: http://llvm.org/viewvc/llvm-project?rev=207204&view=rev
Log:
tsan: better reports for "double lock of a mutex"
+ fixes crashes due to races on symbolizer, see:
https://code.google.com/p/thread-sanitizer/issues/detail?id=55


Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h
    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_mutex.cc
    compiler-rt/trunk/lib/tsan/tests/unit/tsan_flags_test.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc?rev=207204&r1=207203&r2=207204&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc Fri Apr 25 02:42:55 2014
@@ -41,6 +41,7 @@ static void ParseFlags(Flags *f, const c
   ParseFlag(env, &f->report_bugs, "report_bugs", "");
   ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks", "");
   ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked", "");
+  ParseFlag(env, &f->report_mutex_bugs, "report_mutex_bugs", "");
   ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe", "");
   ParseFlag(env, &f->report_atomic_races, "report_atomic_races", "");
   ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics", "");
@@ -75,6 +76,7 @@ void InitializeFlags(Flags *f, const cha
   f->report_bugs = true;
   f->report_thread_leaks = true;
   f->report_destroy_locked = true;
+  f->report_mutex_bugs = true;
   f->report_signal_unsafe = true;
   f->report_atomic_races = true;
   f->force_seq_cst_atomics = false;

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h?rev=207204&r1=207203&r2=207204&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h Fri Apr 25 02:42:55 2014
@@ -37,6 +37,8 @@ struct Flags : CommonFlags, DDFlags {
   bool report_thread_leaks;
   // Report destruction of a locked mutex?
   bool report_destroy_locked;
+  // Report incorrect usages of mutexes and mutex annotations?
+  bool report_mutex_bugs;
   // Report violations of async signal-safety
   // (e.g. malloc() call from a signal handler).
   bool report_signal_unsafe;

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=207204&r1=207203&r2=207204&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Fri Apr 25 02:42:55 2014
@@ -74,6 +74,8 @@ static const char *ReportTypeString(Repo
     return "thread leak";
   if (typ == ReportTypeMutexDestroyLocked)
     return "destroy of a locked mutex";
+  if (typ == ReportTypeMutexDoubleLock)
+    return "double lock of a mutex";
   if (typ == ReportTypeSignalUnsafe)
     return "signal-unsafe call inside of a signal";
   if (typ == ReportTypeErrnoInSignal)

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=207204&r1=207203&r2=207204&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Fri Apr 25 02:42:55 2014
@@ -24,6 +24,7 @@ enum ReportType {
   ReportTypeUseAfterFree,
   ReportTypeThreadLeak,
   ReportTypeMutexDestroyLocked,
+  ReportTypeMutexDoubleLock,
   ReportTypeSignalUnsafe,
   ReportTypeErrnoInSignal,
   ReportTypeDeadlock

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc?rev=207204&r1=207203&r2=207204&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Fri Apr 25 02:42:55 2014
@@ -117,15 +117,16 @@ void MutexLock(ThreadState *thr, uptr pc
   SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
   thr->fast_state.IncrementEpoch();
   TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
+  bool report_double_lock = false;
   if (s->owner_tid == SyncVar::kInvalidTid) {
     CHECK_EQ(s->recursion, 0);
     s->owner_tid = thr->tid;
     s->last_lock = thr->fast_state.raw();
   } else if (s->owner_tid == thr->tid) {
     CHECK_GT(s->recursion, 0);
-  } else {
-    Printf("ThreadSanitizer WARNING: double lock of mutex %p\n", addr);
-    PrintCurrentStack(thr, pc);
+  } else if (flags()->report_mutex_bugs && !s->is_broken) {
+    s->is_broken = true;
+    report_double_lock = true;
   }
   if (s->recursion == 0) {
     StatInc(thr, StatMutexLock);
@@ -142,7 +143,19 @@ void MutexLock(ThreadState *thr, uptr pc
       ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
     ctx->dd->MutexAfterLock(&cb, &s->dd, true, try_lock);
   }
+  u64 mid = s->GetId();
   s->mtx.Unlock();
+  // Can't touch s after this point.
+  if (report_double_lock) {
+    ThreadRegistryLock l(ctx->thread_registry);
+    ScopedReport rep(ReportTypeMutexDoubleLock);
+    rep.AddMutex(mid);
+    StackTrace trace;
+    trace.ObtainCurrent(thr, pc);
+    rep.AddStack(&trace);
+    rep.AddLocation(addr, 1);
+    OutputReport(ctx, rep);
+  }
   if (flags()->detect_deadlocks) {
     Callback cb(thr, pc);
     ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));

Modified: compiler-rt/trunk/lib/tsan/tests/unit/tsan_flags_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/tsan_flags_test.cc?rev=207204&r1=207203&r2=207204&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/tests/unit/tsan_flags_test.cc (original)
+++ compiler-rt/trunk/lib/tsan/tests/unit/tsan_flags_test.cc Fri Apr 25 02:42:55 2014
@@ -42,6 +42,7 @@ static const char *options1 =
   " report_bugs=0"
   " report_thread_leaks=0"
   " report_destroy_locked=0"
+  " report_mutex_bugs=0"
   " report_signal_unsafe=0"
   " report_atomic_races=0"
   " force_seq_cst_atomics=0"
@@ -86,6 +87,7 @@ static const char *options2 =
   " report_bugs=true"
   " report_thread_leaks=true"
   " report_destroy_locked=true"
+  " report_mutex_bugs=true"
   " report_signal_unsafe=true"
   " report_atomic_races=true"
   " force_seq_cst_atomics=true"
@@ -130,6 +132,7 @@ void VerifyOptions1(Flags *f) {
   EXPECT_EQ(f->report_bugs, 0);
   EXPECT_EQ(f->report_thread_leaks, 0);
   EXPECT_EQ(f->report_destroy_locked, 0);
+  EXPECT_EQ(f->report_mutex_bugs, 0);
   EXPECT_EQ(f->report_signal_unsafe, 0);
   EXPECT_EQ(f->report_atomic_races, 0);
   EXPECT_EQ(f->force_seq_cst_atomics, 0);
@@ -174,6 +177,7 @@ void VerifyOptions2(Flags *f) {
   EXPECT_EQ(f->report_bugs, true);
   EXPECT_EQ(f->report_thread_leaks, true);
   EXPECT_EQ(f->report_destroy_locked, true);
+  EXPECT_EQ(f->report_mutex_bugs, true);
   EXPECT_EQ(f->report_signal_unsafe, true);
   EXPECT_EQ(f->report_atomic_races, true);
   EXPECT_EQ(f->force_seq_cst_atomics, true);





More information about the llvm-commits mailing list