diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-04-25 08:21:30 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-04-25 08:21:30 +0000 |
commit | 2a10d45fc5321f31c5a0cb8ccf8e17c5d2a67ed2 (patch) | |
tree | 97dcc561ac3314b58491159cb504fb816ea363db | |
parent | 087f9f66700726d1f4e6a70cdac3b9202c857f9f (diff) |
tsan: improve "read unlock of a write locked mutex" report
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@207208 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/tsan/rtl/tsan_report.cc | 2 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_report.h | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_mutex.cc | 22 | ||||
-rw-r--r-- | test/tsan/mutex_bad_read_unlock.cc | 20 |
4 files changed, 41 insertions, 4 deletions
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index 6875c4cad..98a7d0f4d 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -78,6 +78,8 @@ static const char *ReportTypeString(ReportType typ) { return "double lock of a mutex"; if (typ == ReportTypeMutexBadUnlock) return "unlock of an unlocked mutex (or by a wrong thread)"; + if (typ == ReportTypeMutexBadReadUnlock) + return "read unlock of a write locked mutex"; if (typ == ReportTypeSignalUnsafe) return "signal-unsafe call inside of a signal"; if (typ == ReportTypeErrnoInSignal) diff --git a/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h index 5b643351b..7c14eff18 100644 --- a/lib/tsan/rtl/tsan_report.h +++ b/lib/tsan/rtl/tsan_report.h @@ -26,6 +26,7 @@ enum ReportType { ReportTypeMutexDestroyLocked, ReportTypeMutexDoubleLock, ReportTypeMutexBadUnlock, + ReportTypeMutexBadReadUnlock, ReportTypeSignalUnsafe, ReportTypeErrnoInSignal, ReportTypeDeadlock diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc index 4f6a2d09b..ae6e4f798 100644 --- a/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -249,18 +249,32 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) { SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true); thr->fast_state.IncrementEpoch(); TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId()); + bool report_bad_unlock = false; if (s->owner_tid != SyncVar::kInvalidTid) { - Printf("ThreadSanitizer WARNING: read unlock of a write locked mutex %p\n", - addr); - PrintCurrentStack(thr, pc); + if (flags()->report_mutex_bugs && !s->is_broken) { + s->is_broken = true; + report_bad_unlock = true; + } } ReleaseImpl(thr, pc, &s->read_clock); if (flags()->detect_deadlocks && s->recursion == 0) { Callback cb(thr, pc); ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false); } + u64 mid = s->GetId(); s->mtx.Unlock(); - thr->mset.Del(s->GetId(), false); + // Can't touch s after this point. + thr->mset.Del(mid, false); + if (report_bad_unlock) { + ThreadRegistryLock l(ctx->thread_registry); + ScopedReport rep(ReportTypeMutexBadReadUnlock); + 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/test/tsan/mutex_bad_read_unlock.cc b/test/tsan/mutex_bad_read_unlock.cc new file mode 100644 index 000000000..486600dd0 --- /dev/null +++ b/test/tsan/mutex_bad_read_unlock.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s +extern "C" void AnnotateRWLockAcquired(const char *f, int l, void *m, long rw); +extern "C" void AnnotateRWLockReleased(const char *f, int l, void *m, long rw); + +int main() { + int m = 0; + AnnotateRWLockAcquired(__FILE__, __LINE__, &m, 1); + AnnotateRWLockReleased(__FILE__, __LINE__, &m, 0); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: read unlock of a write locked mutex +// CHECK: #0 AnnotateRWLockReleased +// CHECK: #1 main +// CHECK: Location is stack of main thread. +// CHECK: Mutex {{.*}}) created at: +// CHECK: #0 AnnotateRWLockAcquired +// CHECK: #1 main +// CHECK: SUMMARY: ThreadSanitizer: read unlock of a write locked mutex + |