sanitizer_deadlock_suppression.patch (3259B)
1 Add support for suppressing corner cases of recursive locking that TSAN 2 normally doesn't allow. 3 4 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp 5 index ccb7065b07ae..58cfc5e1a1fb 100644 6 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp 7 +++ b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp 8 @@ -15,6 +15,7 @@ 9 #include "sanitizer_allocator_internal.h" 10 #include "sanitizer_placement_new.h" 11 #include "sanitizer_mutex.h" 12 +#include "sanitizer_stackdepot.h" 13 14 #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1 15 16 @@ -162,8 +163,19 @@ void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) { 17 18 SpinMutexLock lk(&mtx); 19 MutexEnsureID(lt, m); 20 - if (wlock) // Only a recursive rlock may be held. 21 - CHECK(!dd.isHeld(<->dd, m->id)); 22 + // Only a recursive rlock may be held. 23 + if (wlock && dd.isHeld(<->dd, m->id)) { 24 + // Get stack traces from where the lock is already held. 25 + u32 held_stk = dd.findLockContext(<->dd, m->id); 26 + if (!cb->IsDeadlockSuppressed(held_stk)) { 27 + stk = stk ? stk : cb->Unwind(); 28 + if (!cb->IsDeadlockSuppressed(stk)) { 29 + // We could avoid calling this twice, by storing the result above, but 30 + // we do want the error message to be unchanged. 31 + CHECK(!dd.isHeld(<->dd, m->id)); 32 + } 33 + } 34 + } 35 if (!trylock) 36 dd.addEdges(<->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid()); 37 dd.onLockAfter(<->dd, m->id, stk); 38 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h 39 index 7f461c98bade..252e62e05622 100644 40 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h 41 +++ b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h 42 @@ -66,6 +66,7 @@ struct DDCallback { 43 44 virtual u32 Unwind() { return 0; } 45 virtual int UniqueTid() { return 0; } 46 + virtual bool IsDeadlockSuppressed(u32 stk) { return false; } 47 48 protected: 49 ~DDCallback() {} 50 diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp 51 index 2a8aa1915c9a..1df8acfd7fd0 100644 52 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp 53 +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp 54 @@ -15,8 +15,10 @@ 55 56 #include "tsan_rtl.h" 57 #include "tsan_flags.h" 58 +#include "tsan_mman.h" 59 #include "tsan_sync.h" 60 #include "tsan_report.h" 61 +#include "tsan_suppressions.h" 62 #include "tsan_symbolize.h" 63 #include "tsan_platform.h" 64 65 @@ -39,6 +41,21 @@ struct Callback final : public DDCallback { 66 67 StackID Unwind() override { return CurrentStackId(thr, pc); } 68 int UniqueTid() override { return thr->tid; } 69 + 70 + bool IsDeadlockSuppressed(u32 stk) override { 71 + bool result = false; 72 + if (stk) { 73 + Suppression *supp = nullptr; 74 + ReportStack *rs = SymbolizeStackId(stk); 75 + rs->suppressable = true; 76 + result = IsSuppressed(ReportTypeDeadlock, rs, &supp); 77 + if (rs->frames) { 78 + rs->frames->ClearAll(); 79 + } 80 + DestroyAndFree(rs); 81 + } 82 + return result; 83 + } 84 }; 85 86 void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {