Skip to content

Commit 71a7a03

Browse files
authored
Merge pull request #230 from thisisthepy/feat/tp-tsan-access-frame
Test: Count a TSan report only when the racing access is in the extension
2 parents 67dc1d2 + 921a483 commit 71a7a03

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

‎python-multiplatform-ksp/src/test/python/test_free_threaded.py‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,20 @@ def _tsan_launcher(tmp: Path) -> Path | None:
666666
return launcher if link.returncode == 0 else None
667667

668668

669+
def _access_is_ours(block: str) -> bool:
670+
"""A report counts when one of its two racing accesses was made by the extension itself: the
671+
first stack frame of that access outside the sanitizer runtime is in `ftmod` (generated C or the
672+
header). A race whose accesses are inside libpython (seen on Linux CI: two `PyUnicode_FromString`
673+
memcpys into memory the uninstrumented allocator had handed from one thread to another) is not
674+
about this extension, even when an extension frame calls it further up."""
675+
for part in block.split("\n\n")[:2]:
676+
frames = [ln for ln in part.splitlines() if ln.strip().startswith("#")]
677+
first = next((f for f in frames if "libtsan" not in f and "sanitizer_common" not in f), "")
678+
if "ftmod" in first:
679+
return True
680+
return False
681+
682+
669683
def _tsan_reports(built, tmp: Path, launcher: Path, rt: Path | None) -> tuple[int, bool]:
670684
result, path, _ = built
671685
flags = list(cbuild.DEFAULT_FLAGS) + ["-O1", "-g", "-fno-omit-frame-pointer", "-fsanitize=thread"]
@@ -682,7 +696,7 @@ def _tsan_reports(built, tmp: Path, launcher: Path, rt: Path | None) -> tuple[in
682696
# CPython itself (seen on Linux CI). Count only reports with a frame of the extension or the
683697
# header: those are the accesses this test is about.
684698
blocks = out.split("WARNING: ThreadSanitizer")[1:]
685-
ours = [b for b in blocks if "ftmod" in b or " tp_" in b]
699+
ours = [b for b in blocks if _access_is_ours(b)]
686700
_tsan_reports.first = ("WARNING: ThreadSanitizer" + ours[0])[:4000] if ours else ""
687701
return len(ours), "TSAN-RUN-DONE" in out
688702

0 commit comments

Comments
 (0)