Skip to content

test(anr): Use pure-JS busy work so ANR stack samples capture longWork#22133

Open
mydea wants to merge 1 commit into
developfrom
test/anr-stabilize-stack-sampling
Open

test(anr): Use pure-JS busy work so ANR stack samples capture longWork#22133
mydea wants to merge 1 commit into
developfrom
test/anr-stabilize-stack-sampling

Conversation

@mydea

@mydea mydea commented Jul 9, 2026

Copy link
Copy Markdown
Member

The ANR integration tests intermittently failed because the captured stacktrace was missing the required longWork frame — the sample showed only node:internal/timers frames (processTimers/listOnTimeout/insert) instead, and debug_meta was absent.

Root cause: longWork blocked the event loop via crypto.pbkdf2Sync, a native addon call. The ANR worker samples the main thread through the inspector, which can only pause at a JS safepoint — V8 cannot pause inside a native call, so the pause resolves only after pbkdf2Sync returns. When ANR fired near the tail of longWork, the pause landed after the call had returned and control had popped back to the timer dispatch, so the sampled stack missed longWork entirely. longWork blocks ~880ms locally (well over the 100ms threshold), so this was a sampling-boundary race, not a too-short block.

This replaces the native crypto busy-work with a pure-JS CPU loop in every ANR scenario, across both the node-core and node integration test suites. V8 can now sample inside longWork, so it reliably appears on the captured stack. longWork stays defined locally in each scenario to preserve the per-file filename assertions (e.g. isolated.mjs).

Verified locally: both suites pass 12/12 across repeated runs.

Fixes #21702

🤖 Generated with Claude Code

The ANR tests intermittently failed because the captured stacktrace was missing
the required `longWork` frame — the sample showed only `node:internal/timers`
frames instead.

Root cause: `longWork` blocked the event loop via `crypto.pbkdf2Sync`, a native
addon call. The ANR worker samples the main thread through the inspector, which
can only pause at a JS safepoint — V8 cannot pause inside a native call, so the
pause resolves only after `pbkdf2Sync` returns. When ANR fired near the tail of
`longWork`, the pause landed after the call returned and control had popped back
to the timer dispatch, so the sampled stack missed `longWork` entirely.

Replace the native crypto busy-work with a pure-JS CPU loop in every ANR
scenario (both node-core and node integration tests). V8 can now sample inside
`longWork`, so it reliably appears on the captured stack. `longWork` stays
defined locally in each scenario to preserve the per-file `filename` assertions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mydea mydea requested a review from timfish July 9, 2026 10:44
@mydea mydea marked this pull request as ready for review July 9, 2026 10:45
@mydea mydea requested a review from a team as a code owner July 9, 2026 10:45
@mydea mydea requested review from JPeer264 and andreiborza and removed request for a team July 9, 2026 10:45
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.

[Flaky CI]: Node Node-Core Integration Tests - suites/anr/test.ts > should report ANR when event loop blocked > CJS

1 participant