aboutsummaryrefslogtreecommitdiff
path: root/tsan.supp
diff options
context:
space:
mode:
Diffstat (limited to 'tsan.supp')
-rw-r--r--tsan.supp22
1 files changed, 22 insertions, 0 deletions
diff --git a/tsan.supp b/tsan.supp
new file mode 100644
index 000000000..da8963854
--- /dev/null
+++ b/tsan.supp
@@ -0,0 +1,22 @@
+# TSAN suppression / options file for zenserver
+#
+# Usage:
+# TSAN_OPTIONS="detect_deadlocks=0 suppressions=$(pwd)/tsan.supp" ./zenserver
+#
+# NOTE: detect_deadlocks=0 is required because the GC's LockState() acquires shared
+# lock scopes on every named cache bucket (m_IndexLock) and every oplog
+# (GcReferenceLocker) simultaneously. With enough buckets/projects/oplogs this
+# easily exceeds TSAN's hard per-thread limit of 128 simultaneously-held locks
+# (all_locks_with_contexts_[128] in sanitizer_deadlock_detector.h:67), causing a
+# CHECK abort. This is a known TSAN limitation, not a real deadlock risk.
+# The long-term fix is to replace the N per-bucket shared-lock pattern in
+# ZenCacheStore::LockState / ProjectStore::LockState with a single coarser
+# "GC epoch" RwLock at the disk-layer / project-store level.
+
+# EASTL's hashtable uses a global gpEmptyBucketArray[2] sentinel shared by all
+# empty hash tables (mnBucketCount == 1). DoFreeNodes unconditionally writes NULL
+# to each bucket slot, including this shared global. Multiple threads concurrently
+# destroying empty EASTL hash_maps all write NULL to gpEmptyBucketArray[0], which
+# TSAN reports as a race. This is benign: the slot is always NULL and writing NULL
+# to it has no observable effect.
+race:eastl::hashtable*DoFreeNodes*