ReviewOS

zig-utils/zig-js

Tests: stabilize deep-source RangeError witness under TSan

#986
Closed chris opened this 9 days ago ·
9 days ago

Parent: #493 Related: #936, #937, #938

Problem

The focused runtime TSan gate fails the test named "deeply nested source raises a catchable RangeError", while the same focused gate passes without TSan. The failure is identical on the exact parent revision 76768e2 and with the #985 runtime-coordination change applied, and the sanitizer reports no data race.

Observed command: zig build test-runtime -Dtsan=true

The ordinary focused runtime gate and the standalone runtime coordinator's normal and TSan tests pass.

Scope

  • Reduce the failing deep-source shape to the smallest deterministic TSan witness.
  • Determine whether TSan's larger frames move the stack-limit boundary, the subprocess expectation uses an unstable depth, or the catchable error is lost on a sanitizer-only path.
  • Preserve the production RangeError behavior and the existing normal-build depth coverage.
  • Pin a deterministic sanitizer-aware test that exercises the same semantic boundary without skipping it.
  • Run the focused normal/TSan gates and the deep-source regression matrix.

No-workaround rule

Do not disable the test under TSan, weaken the RangeError requirement, or select an arbitrary shallower input without proving that it still crosses the guarded production boundary.

9 days ago

Investigating this next from main at 517a538. The first step is an unchanged focused TSan reproduction using the real pinned GC/regex dependencies, under the existing shared 3072 MB machine guard. I am separating the deep-exhaustion checks from the fixed-depth success control before choosing a fix. No failing subcheck has been identified yet, no source fix has landed, and no test depth/assertion or sanitizer coverage has been weakened. Runtime-coordination work in #502 is out of scope; #989 verification is retained and heavy jobs are serialized by the same lock.

9 days ago

Baseline reproduced unchanged on main 517a538 with the real pinned dependencies and Zig 0.17.0-dev.1441. The focused TSan executable built successfully, then runtime "deeply nested source raises a catchable RangeError" exited 1: the harness reported threw Throw / FocusedTestFailed. The trace reaches checkNesting -> nestingLimitReached -> throwUncatchableError while evaluating the deep unary chain; there is no ThreadSanitizer race report in the log. The shared guard sampled a 2161 MB process-tree peak, below the unchanged 3072 MB cap. Raw build/run log: /private/tmp/zig-js-986.rZpO84/baseline-tsan.log on the measurement host. A diagnostic preserving all nine depth-200000 checks plus the depth-300 controls is queued under the same lock to identify whether the exception escapes from the unary check itself or from subsequent fixed-depth evaluation. No source/test change yet.

9 days ago

Repeated the TSan diagnostic three times under the shared 3072 MiB guard. Every run was identical: all nine depth-200000 shapes produced the intended catchable RangeError; parenthesis and template controls passed through depth 256; only the combined shallow bit failed because the template control at depth 300 reached the production stack guard under TSan. Peak sampled process-tree footprint was 808 MiB. The candidate keeps depth 300 for normal builds and uses depth 128 only for the TSan shallow control (4x the guard probe floor); the actual depth-200000 witnesses stay unchanged. Full normal + TSan runtime gates are queued behind the serialized #989 qualification.

9 days ago

Resolved on main by e3e2ca49.

The production stack guard was behaving correctly. Under TSan, template evaluation's larger native frames make the fixed depth-300 "ordinary source" control reach that same guard; the nine actual depth-200000 exhaustion witnesses all continued to return the intended catchable RangeError.

The test now keeps depth 300 in normal builds and uses depth 128 only for the TSan shallow control. That remains four times the stack guard's 32-level probe floor. All nine depth-200000 inputs are byte-for-byte identical across build modes.

Evidence:

  • baseline diagnostic repeated 3 times with identical results
  • all nine depth-200000 shapes produced RangeError: Maximum call stack size exceeded.
  • under TSan, parenthesis and template controls pass through depth 256; template depth 300 reaches the production guard
  • candidate focused normal case: 1/1
  • candidate complete normal runtime matrix: 30/30
  • candidate focused TSan case: 3/3
  • candidate complete TSan runtime matrix: 30/30
  • unchanged 3072 MiB guard; 2820 MiB sampled process-tree peak
  • test-only change; 0 test262 flips

No production limit, production behavior, sanitizer skip, or test expectation was weakened.

Sign in to comment on this issue.