sanitizer_deadlock_suppression_clang_22.patch (3311B)
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 30f5e964939d..2b254e323330 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,9 +15,11 @@ 55 #include <sanitizer_common/sanitizer_stackdepot.h> 56 57 #include "tsan_flags.h" 58 +#include "tsan_mman.h" 59 #include "tsan_platform.h" 60 #include "tsan_report.h" 61 #include "tsan_rtl.h" 62 +#include "tsan_suppressions.h" 63 #include "tsan_symbolize.h" 64 #include "tsan_sync.h" 65 66 @@ -40,6 +42,21 @@ struct Callback final : public DDCallback { 67 68 StackID Unwind() override { return CurrentStackId(thr, pc); } 69 int UniqueTid() override { return thr->tid; } 70 + 71 + bool IsDeadlockSuppressed(u32 stk) override { 72 + bool result = false; 73 + if (stk) { 74 + Suppression *supp = nullptr; 75 + ReportStack *rs = SymbolizeStackId(stk); 76 + rs->suppressable = true; 77 + result = IsSuppressed(ReportTypeDeadlock, rs, &supp); 78 + if (rs->frames) { 79 + rs->frames->ClearAll(); 80 + } 81 + DestroyAndFree(rs); 82 + } 83 + return result; 84 + } 85 }; 86 87 void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {