[llvm-branch-commits] [compiler-rt] [TSan] Lock ScopedErrorReportLock before slot and thread_registry locks (PR #228614)
Vitaly Buka via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Oct 3 14:17:43 PDT 2026
https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/228614
>From 2d7a01735508d80bfbcd365301d826f833301f12 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Fri, 2 Oct 2026 16:21:44 -0700
Subject: [PATCH 1/2] Add CheckNoLocks and keep ReportDestroyLocked
RestoreStack in place
Created using spr 1.3.7
---
compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp | 29 ++++++++------------
compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp | 2 ++
2 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
index 80bda14d728ec..23226f86bf33c 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
@@ -574,34 +574,29 @@ void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
FastState last_lock, StackID creation_stack_id) {
- Tid tid;
- DynamicMutexSet mset;
- uptr tag;
- VarSizeStackTrace last_lock_stack;
- {
- // We need to lock the slot during RestoreStack because it protects
- // the slot journal.
- Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
- ThreadRegistryLock l0(&ctx->thread_registry);
- Lock slots_lock(&ctx->slot_mtx);
- if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(),
- addr, 0, kAccessWrite, &tid, &last_lock_stack, mset,
- &tag))
- return;
- }
-
// Use alloca, because malloc during signal handling deadlocks
ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
// Release locks before symbolizing and outputting the report to avoid
// deadlocks.
{
new (rep) ScopedReport(ReportTypeMutexDestroyLocked);
+ // We need to lock the slot during RestoreStack because it protects
+ // the slot journal.
+ Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
ThreadRegistryLock l0(&ctx->thread_registry);
+ Lock slots_lock(&ctx->slot_mtx);
rep->AddMutex(addr, creation_stack_id);
VarSizeStackTrace trace;
ObtainCurrentStack(thr, pc, &trace);
rep->AddStack(trace, true);
- rep->AddStack(last_lock_stack, true);
+
+ Tid tid;
+ DynamicMutexSet mset;
+ uptr tag;
+ if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(),
+ addr, 0, kAccessWrite, &tid, &trace, mset, &tag))
+ return;
+ rep->AddStack(trace, true);
rep->AddLocation(addr, 1);
}
OutputReport(thr, *rep);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
index 132ef718d39f5..e90d7e8851752 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
@@ -164,6 +164,7 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
}
ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
+ CheckedMutex::CheckNoLocks();
rep_ = New<ReportDesc>();
rep_->typ = typ;
rep_->tag = tag;
@@ -676,6 +677,7 @@ static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {
}
bool OutputReport(ThreadState *thr, ScopedReport &srep) {
+ CheckedMutex::CheckNoLocks();
// These should have been checked in ShouldReport.
// It's too late to check them here, we have already taken locks.
CHECK(flags()->report_bugs);
>From a74331b81d885b13eb7365417e15239a6e181627 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Fri, 2 Oct 2026 19:41:31 -0700
Subject: [PATCH 2/2] Fix clang-format
Created using spr 1.3.7
---
compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
index e90d7e8851752..7d302955374de 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
@@ -843,7 +843,7 @@ void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
}
// Use alloca, because malloc during signal handling deadlocks
- ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
+ ScopedReport* rep = (ScopedReport*)__builtin_alloca(sizeof(ScopedReport));
// Release locks before symbolizing and outputting the report to avoid
// deadlocks.
{
More information about the llvm-branch-commits
mailing list