CI: don't hard-fail on the confirmed TSan-can't-start-here runner limitation
CI / build-and-test (push) Failing after 23s

The real Gitea Actions run on this project's own registered runner just
failed exactly as CONTRIBUTING.md already anticipated it might:
FATAL: ThreadSanitizer: unexpected memory mapping, the same signature
already documented as a sandbox/container seccomp restriction blocking
personality(ADDR_NO_RANDOMIZE), which TSan needs to start at all. Build,
test suite, and ASan/UBSan all passed -- only the TSan step failed, on an
environment issue, not a code issue.

Fixed the CI step itself rather than just noting the failure: it now
classifies each binary's TSan run as PASS, a known flake (that exact
FATAL signature and nothing indicating an actual race was found), or a
real failure (anything else -- a genuine data race, a crash, any other
error). Only a real failure fails the build. Verified the classification
logic locally against four cases (a synthetic real race report, a plain
assertion failure, the known flake signature alone, and a clean pass) --
each classified correctly -- and against this sandbox's own six test
binaries, all six of which hit the real flake (this sandbox has never
been able to run TSan either) and correctly did not fail the build.

This does NOT mean TSan verification is happening in CI -- it means CI no
longer conflates "TSan couldn't start" with "the build is broken."
Updated CONTRIBUTING.md and CLAUDE.md from "whether the runner can execute
TSan is unverified" (a hedge) to the now-confirmed fact that it can't, and
corrected an overclaim in README.md that the suite is "regularly run under
ThreadSanitizer" -- as far as this project has been able to confirm, TSan
has not actually completed a run in any environment it's been built in
yet, local sandbox or CI. ASan/UBSan remain the real, run, load-bearing
sanitizer coverage.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UqJpkdJ6Njnt1pw3CbghzB
This commit is contained in:
2026-09-14 11:53:08 +00:00
co-authored by Claude Sonnet 5
parent 21bcb4640f
commit 0c0ae4f747
4 changed files with 67 additions and 11 deletions
+16 -7
View File
@@ -43,13 +43,22 @@ project's development, see the `reclaim_gate` note in `internal.h`) but do
not do TSan's happens-before race analysis, so they are not a substitute
for it. CI (`.gitea/workflows/ci.yml`, Gitea Actions — this project is
hosted on Gitea, not GitHub) runs on this project's own self-hosted
runner; whether that runner can execute TSan depends on that runner's own
environment, which is not controlled by this repository the way a
hosted-runner VM would be — do not assume CI's TSan step passing means
what it would on an unrestricted machine without having actually checked
what environment the registered runner provides. Treat a change as
TSan-verified only once it has actually passed on a machine confirmed able
to run it, not merely because a CI step reported success.
runner. **Confirmed, not just anticipated: that runner cannot run TSan
either.** The first real CI run on it failed the ThreadSanitizer step with
the exact same signature described above (`FATAL: ThreadSanitizer:
unexpected memory mapping`), consistent with the runner's job containers
using a default seccomp profile that blocks `personality()` the same way
some local sandboxes do. The CI step now detects this specific failure
signature and does not fail the build over it (while still failing hard on
any *other* TSan outcome — a real race, a crash, anything without that
exact signature) — see the step's own comment in `ci.yml` for the
detection logic. This means **CI's ThreadSanitizer step passing is not
evidence that TSan actually ran** on a given push; it may just mean the
runner couldn't start it and the step correctly didn't treat that as a
failure. Treat a change as TSan-verified only once it has actually passed
on a machine confirmed able to run it (a local machine or container with
`personality(ADDR_NO_RANDOMIZE)` available), not merely because CI is
green.
**A second, separate environment quirk, also observed directly rather than
assumed:** in the same kind of sandboxed environment, an ASan/UBSan-built