aboutsummaryrefslogtreecommitdiff
path: root/tsan.supp
diff options
context:
space:
mode:
Diffstat (limited to 'tsan.supp')
-rw-r--r--tsan.supp49
1 files changed, 37 insertions, 12 deletions
diff --git a/tsan.supp b/tsan.supp
index 93398da67..6dfe4e393 100644
--- a/tsan.supp
+++ b/tsan.supp
@@ -1,17 +1,42 @@
-# TSAN suppression / options file for zenserver
+# ThreadSanitizer options and suppression patterns for Zen
#
-# Usage:
-# TSAN_OPTIONS="detect_deadlocks=0 suppressions=$(pwd)/tsan.supp" ./zenserver
+# This is a mixed-format file:
#
-# 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.
+# key=value TSAN runtime option; parsed by xmake's sanitizer.options
+# rule and set directly in TSAN_OPTIONS. When this file is also
+# passed as suppressions=<path>, the TSAN runtime silently skips
+# these lines (they don't match the type:pattern format).
+# race:... race condition suppression pattern
+# mutex:... mutex suppression pattern
+# signal:... signal suppression pattern
+# thread:... thread suppression pattern
+# # comment line
+# <blank> ignored
+#
+# xmake passes the file via TSAN_OPTIONS=suppressions=<path> when both the
+# compiler is Clang or GCC (not MSVC/clang-cl) and the platform is Linux or
+# macOS. This is handled by the sanitizer.options rule in xmake.lua.
+#
+# If you run a binary directly (not via xmake run / xmake test) set
+# TSAN_OPTIONS manually, e.g.:
+# TSAN_OPTIONS="detect_deadlocks=0:suppressions=$(pwd)/tsan.supp" ./zenserver
+
+# Required because 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, 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.
+#
+# NOTE: this line will produce a TSAN warning along the lines of:
+# WARNING: failed to parse suppression 'detect_deadlocks=0'
+# This is expected and harmless. xmake's sanitizer.options rule parses
+# key=value lines from this file and injects them into TSAN_OPTIONS directly.
+# When the file is subsequently passed to the TSAN runtime as suppressions=<path>,
+# the runtime does not understand key=value syntax, prints the warning, and skips
+# the line. The option is already active via TSAN_OPTIONS; nothing is lost.
+detect_deadlocks=0
# EASTL's hashtable uses a global gpEmptyBucketArray[2] sentinel shared by all
# empty hash tables (mnBucketCount == 1). DoFreeNodes unconditionally writes NULL