diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-04-25 07:42:55 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-04-25 07:42:55 +0000 |
commit | c845decce1eaf0047b29bf44fef758ccd873be2d (patch) | |
tree | 613602abd1533386dd36c7fbcfb710ccfd844571 /compiler-rt | |
parent | 3212b18bbf8458cc9eabbb8938ffcef68af7473c (diff) | |
download | bcm5719-llvm-c845decce1eaf0047b29bf44fef758ccd873be2d.tar.gz bcm5719-llvm-c845decce1eaf0047b29bf44fef758ccd873be2d.zip |
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
llvm-svn: 207204
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_flags.cc | 2 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_flags.h | 2 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_report.cc | 2 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_report.h | 1 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc | 19 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc | 4 |
6 files changed, 27 insertions, 3 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/compiler-rt/lib/tsan/rtl/tsan_flags.cc index 2dd9a0c7fe9..143120010a1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_flags.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.cc @@ -41,6 +41,7 @@ static void ParseFlags(Flags *f, const char *env) { 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 char *env) { 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; diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.h b/compiler-rt/lib/tsan/rtl/tsan_flags.h index 2a765b135f6..cd489d66843 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_flags.h +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.h @@ -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; diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc index 8beccd29f50..b0ad670da3e 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -74,6 +74,8 @@ static const char *ReportTypeString(ReportType typ) { 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) diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h index b37d00bec37..aaa562b5def 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.h +++ b/compiler-rt/lib/tsan/rtl/tsan_report.h @@ -24,6 +24,7 @@ enum ReportType { ReportTypeUseAfterFree, ReportTypeThreadLeak, ReportTypeMutexDestroyLocked, + ReportTypeMutexDoubleLock, ReportTypeSignalUnsafe, ReportTypeErrnoInSignal, ReportTypeDeadlock diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc index e26e142368f..83e76968b32 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -117,15 +117,16 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) { 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, uptr addr, int rec, bool try_lock) { 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)); diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc b/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc index 33ddaaae2dd..3227d27ec92 100644 --- a/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc +++ b/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc @@ -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); |