Skip to content

selfcheck: --no-wasm-dynamic-tiering, so Windows no longer aborts checks at exit - #56

Closed
shayshahal wants to merge 1 commit into
mainfrom
kit/selfcheck-wasm-exit
Closed

shayshahal wants to merge 1 commit into
mainfrom
kit/selfcheck-wasm-exit

Conversation

@shayshahal

Copy link
Copy Markdown
Owner

The crash

On Windows, a selfcheck that calls process.exit right after loading its .ts files sometimes died with libuv's Assertion failed: !(handle->flags & UV_HANDLE_CLOSING), file src\win\async.c, line 94 (exit 3221226505), after all its checks had passed. Today it turned four runs red and refused one push.

Cause

Node's TypeScript type-stripper is WebAssembly. When V8 is still recompiling the stripper's hot functions in the background (dynamic tiering), process.exit closes the libuv handle that task reports back on. This is nodejs/node#56645, fixed by #61999, which isn't in Node 26.2.

How it was pinned down:

  • Bisected to env/update.ts's module: a two-line file that imports it and calls process.exit(0) crashed 30 of 30 times, run one at a time.
  • It's not one part of the file: each half alone doesn't crash, and neither does padding a non-crashing variant to the same size. It needs both install and autoUpdate.
  • It disappears under --jitless, --liftoff-only, --no-liftoff and --no-wasm-dynamic-tiering. Turning off the background compile-task threads doesn't help.

Fix

src/selfcheck.ts starts each check with --no-wasm-dynamic-tiering. That's one line, the 33 check files stay as they are, and real wf commands are untouched.

Measured

  • env/update.selfcheck.ts one at a time: 10 of 30 crashed before, 0 of 30 after.
  • The whole selfcheck, 30 runs: 6 red before, 0 after. Each run takes 0.89 s → 1.16 s.
  • Real wf commands (status, next, an unknown command, through both entries): none crashed in 40 runs. They do more work before they exit. If one ever does, the same flag or setting process.exitCode instead of calling process.exit is the fix.

… no longer aborts it at exit

On Windows a selfcheck that calls process.exit right after loading its .ts files died with libuv's
!(handle->flags & UV_HANDLE_CLOSING) assertion (exit 3221226505), all its checks green. Node's type
stripper is WebAssembly; V8 was still recompiling its hot functions in the background when
process.exit closed the handle that task reports back on: nodejs/node#56645, fixed by #61999, not in
Node 26.2. Bisected to env/update.ts's module (30 of 30 crashes one at a time in a two-line repro),
gone under --jitless, --liftoff-only, --no-liftoff and --no-wasm-dynamic-tiering.

The whole selfcheck, 30 runs: 6 red before, 0 after; 0.89 s -> 1.16 s a run. Real wf commands
were not seen to crash (40 runs): they do more work before they exit.
@shayshahal

Copy link
Copy Markdown
Owner Author

Closed: upgraded Node instead. The fix (nodejs/node#61999) shipped in Node 26.7.0; this machine went 26.2.0 → 26.10.0 (nodejs.org MSI). On 26.10.0, without the flag: the two-line repro crashed 0 of 30 runs (30 of 30 on 26.2.0), and the whole selfcheck was 0 red in 30 runs at 0.7–0.86 s a run, faster than the flag's 1.16 s.

@shayshahal shayshahal closed this Oct 4, 2026
@shayshahal
shayshahal deleted the kit/selfcheck-wasm-exit branch October 4, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant