fix: cancel uncleared timers and abort listeners left by lost Promise.race branches - #176
Merged
Merged
Conversation
….race branches Several sites raced real work against a setTimeout-based delay or an AbortSignal listener and never cleaned up the loser. A ref'd pending timer keeps the event loop alive, and an uncancelled listener leaks on session-lifetime signals. The worst instance kept iOS harness runs alive for ~25s after test results printed, via two uncancelled 30s timers in the XCTest agent's shutdown wait. Adds two shared, cancellable primitives to packages/tools (delay(), waitForAbort()) and uses them to fix all six known sites: XCTest agent graceful shutdown, Android's waitWithSignal (both directions) and its emulator-boot observation timeout, the iOS/Vega app session poll loops (dispose() no longer blocks on a live poll delay), and the jest package's startup-crash race. Private per-file duplicates of delay/waitForAbort are removed in favor of the shared helpers.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
# Conflicts: # packages/platform-vega/src/runner.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this?
Harness runs on iOS could linger for up to ~25 seconds after test results printed, because the CLI process could not exit. Several places raced real work against a
setTimeout-based delay or anAbortSignallistener but never cleaned up the losing side of the race. A left-over ref'd timer keeps the event loop alive until it fires; a left-over abort listener leaks on signals that live for the whole session.How does it work?
Two small cancellable primitives are added to
packages/tools:delay(ms)returns{ promise, cancel }so a race loser's timer can be cleared immediately, andwaitForAbort(signal)returns{ promise, cancel }so a race loser's'abort'listener can be detached immediately. Every site that raced against a bare timer or listener now clears the loser in afinally:waitWithSignal, used by three 1-second poll loops against a session-lifetime signal, now cleans up both directions of the race, plus the emulator-boot observation timeout.dispose()is called, instead of blocking teardown on a live 1-second wait.Private per-file duplicates of
delay/waitForAbortare removed in favor of the shared helpers. Sites that are already safe are left untouched, notably anywhere usingAbortSignal.timeout()(its internal timer is unref'd and can't hold the process open) and the sequential (non-raced) delays in the crash-artifact polling code.Why is this useful?
Every test run now exits promptly after results print instead of waiting out a stale timer, and long test suites no longer accumulate leaked
'abort'listeners on session-lifetime signals.