summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-04-25 07:55:11 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-04-25 07:55:11 +0000
commit2c87108a42081e7211c7972949014a9b9145aafc (patch)
tree99a6ef29173d4baca90cba4427b4b9baa1e20571 /compiler-rt
parentea014b787a59e53f40b48d8f47b9a5f9bb0bfcfe (diff)
downloadbcm5719-llvm-2c87108a42081e7211c7972949014a9b9145aafc.tar.gz
bcm5719-llvm-2c87108a42081e7211c7972949014a9b9145aafc.zip
tsan: better report for bad mutex unlocks
+ fixes crashes due to races on symbolizer, see https://code.google.com/p/thread-sanitizer/issues/detail?id=55 llvm-svn: 207206
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_report.cc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_report.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc27
-rw-r--r--compiler-rt/test/tsan/mutex_bad_unlock.cc18
4 files changed, 37 insertions, 11 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc
index b0ad670da3e..6875c4cad44 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc
@@ -76,6 +76,8 @@ static const char *ReportTypeString(ReportType typ) {
return "destroy of a locked mutex";
if (typ == ReportTypeMutexDoubleLock)
return "double lock of a mutex";
+ if (typ == ReportTypeMutexBadUnlock)
+ return "unlock of an unlocked mutex (or by a wrong thread)";
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 aaa562b5def..5b643351bce 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.h
@@ -25,6 +25,7 @@ enum ReportType {
ReportTypeThreadLeak,
ReportTypeMutexDestroyLocked,
ReportTypeMutexDoubleLock,
+ ReportTypeMutexBadUnlock,
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 83e76968b32..4f6a2d09bba 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -170,18 +170,11 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
int rec = 0;
- if (s->recursion == 0) {
- if (!s->is_broken) {
- s->is_broken = true;
- Printf("ThreadSanitizer WARNING: unlock of unlocked mutex %p\n", addr);
- PrintCurrentStack(thr, pc);
- }
- } else if (s->owner_tid != thr->tid) {
- if (!s->is_broken) {
+ bool report_bad_unlock = false;
+ if (s->recursion == 0 || s->owner_tid != thr->tid) {
+ if (flags()->report_mutex_bugs && !s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex %p is unlocked by wrong thread\n",
- addr);
- PrintCurrentStack(thr, pc);
+ report_bad_unlock = true;
}
} else {
rec = all ? s->recursion : 1;
@@ -199,7 +192,19 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
Callback cb(thr, pc);
ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
}
+ u64 mid = s->GetId();
s->mtx.Unlock();
+ // Can't touch s after this point.
+ if (report_bad_unlock) {
+ ThreadRegistryLock l(ctx->thread_registry);
+ ScopedReport rep(ReportTypeMutexBadUnlock);
+ 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/test/tsan/mutex_bad_unlock.cc b/compiler-rt/test/tsan/mutex_bad_unlock.cc
new file mode 100644
index 00000000000..dce815cafc5
--- /dev/null
+++ b/compiler-rt/test/tsan/mutex_bad_unlock.cc
@@ -0,0 +1,18 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+extern "C" void AnnotateRWLockReleased(const char *f, int l, void *m, long rw);
+
+int main() {
+ int m = 0;
+ AnnotateRWLockReleased(__FILE__, __LINE__, &m, 1);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread)
+// CHECK: #0 AnnotateRWLockReleased
+// CHECK: #1 main
+// CHECK: Location is stack of main thread.
+// CHECK: Mutex M1 ({{.*}}) created at:
+// CHECK: #0 AnnotateRWLockReleased
+// CHECK: #1 main
+// CHECK: SUMMARY: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread)
+
OpenPOWER on IntegriCloud