ReviewOS

home-lang/home

Worker destruction: terminate in-flight fetch without hanging

#598
Closed chris opened this 10 days ago ·
10 days ago

Follow-up to #66 after the native worker corpus promotion in e1523b1.

Reproduction on the pinned Bun corpus copy:

HOME_NATIVE_VM=1 HOME_CORPUS_FULL_VM=1 ./zig-out/bin/home-debug test --preload ./packages/runtime/test/bun-corpus/preload.ts ./packages/runtime/test/bun-corpus/js/node/worker_threads/worker_destruction.test.ts

Observed on Home native Debug:

  • Bun.connect worker-termination case passes.
  • Bun.listen worker-termination case passes.
  • The fetch worker-termination case does not complete; the process was manually interrupted after more than 60 seconds.

Keep the upstream test body and lifecycle semantics unchanged. Trace cancellation and teardown of an in-flight fetch when its Worker terminates, ensure the worker and parent event loops quiesce naturally, add direct lifecycle/destruction coverage, and then admit the unchanged complete file to the native corpus runner. A timeout, skip, method exclusion, or relaxed assertion is not completion.

The adjacent complete worker_threads.test.ts Debug deadline is separate: #482 documents that the original 100 MiB eval-source workload passes unchanged in ReleaseFast. This issue is specifically the fetch-on-destruction hang.

10 days ago

Fixed and published on main in eae013190 (fix(runtime): preserve zero worker exit completion), authored and committed by Chris Breuer without coauthors.

Root cause: node:worker_threads cached a naturally completed worker as numeric exit code 0, but terminate() checked that state by truthiness. A terminate call arriving after the close event therefore installed a new listener and waited forever for a second close event. The fix distinguishes only undefined (no cached completion) from every valid numeric exit code.

Verification retained all original workloads and deadlines:

  • Old Home binary fails the new deterministic regression after five seconds at first terminate after exit 0.
  • New native regression covers natural exit 0, natural exit 2, repeated terminate calls, concurrent terminate promise identity, and terminate after forced exit; 20/20 independent Debug processes pass.
  • Unchanged worker_thread_check.ts fetch: 10/10 independent processes pass, each running the original 5 × 10-worker lifecycle (500 successful worker terminations across the sweep).
  • Complete unchanged worker_destruction.test.ts: 3 pass / 0 fail in Debug and ReleaseSafe; pinned Bun 4982b91e3 also reports 3/3.
  • Adjacent worker suites: 29 pass / 1 upstream TODO / 0 fail.
  • Full promoted matrix after the fix: 264 pass / 3 upstream release-mode skips / 1 upstream TODO / 0 fail across 16 files.
  • Ordinary corpus route reports 3 pass / 0 fail / 0 unsupported / 0 TODO with no allocator diagnostics. Its preload path now preserves the sentinel allocation type found by this route-level verification.
  • Builtin generator/ABI tests: 3 pass / 117 assertions.
  • Stable home_rt: 1,816 pass / 19 skip / 0 fail.
  • Debug and ReleaseSafe builds pass; the new regression and destruction corpus both pass using the exact ReleaseSafe artifact.

No timeout, skip, retry, fixture workload, or HTTP behavior was changed. Linux/Windows and the separate Debug eval-source performance boundary remain under #66/#482.

Sign in to comment on this issue.