Skip to content

Commit e15f7e3

Browse files
committed
Add tsan suppression
1 parent db30f1b commit e15f7e3

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

.github/run-single-config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ def main() -> int:
8989
repo_root = Path(__file__).resolve().parents[1]
9090
env = compiler_env(args.compiler, os.environ)
9191

92+
if args.sanitizer == "tsan":
93+
supp = repo_root / "tests" / "tsan.supp"
94+
env["TSAN_OPTIONS"] = f"suppressions={supp}"
95+
9296
cmake_args = [
9397
"cmake",
9498
"-S",

tests/tsan.supp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# TSan suppression file for GameNetworkingSockets tests.
2+
#
3+
# Lock-order inversion: ConnectionLock -> TableLock in BInitConnection
4+
#
5+
# The normal lock order is TableLock first, then ConnectionLock (acquire the
6+
# table lock to look up a connection by handle, then lock the connection).
7+
# BInitConnection inverts this: it holds the new connection's ConnectionLock
8+
# and then acquires the TableLock to register the connection in the table.
9+
#
10+
# This is safe because:
11+
# 1) The SteamNetworkingGlobalLock is held across both paths, so only one
12+
# thread can be in either code path at a time -- actual concurrent
13+
# deadlock is impossible.
14+
# 2) The connection being registered is brand new and not yet in the table,
15+
# so no thread holding the TableLock could be waiting on this
16+
# connection's lock.
17+
#
18+
# The reverse direction (TableLock -> ConnectionLock) already uses TryLock
19+
# with a retry loop in InternalGetConnectionByHandle specifically to handle
20+
# the rare case where the order is inverted.
21+
deadlock:SteamNetworkingSocketsLib::CSteamNetworkConnectionBase::BInitConnection

0 commit comments

Comments
 (0)