ReviewOS

home-lang/home

Nested workers: stop and join descendants before parent VM teardown

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

Follow-up to #66, #461, #465, and #469. A bounded native regression blocks a parent Worker and its nested child, queues a transferred port to the child, then terminates the parent. Home lets the child resume and execute its queued handler (shared count 1, expected 0). The Node control suppresses it. Seven ordinary-worker inbox cases pass; this nested failure remains explicit.

Worker inherits ContextDestructionObserver without an override that terminates its child. Parent teardown only clears the context pointer. Implement descendant lifecycle ownership: request termination and join descendants before destroying their parent VM. Preserve error and exit behavior, owner-thread listener and poll cleanup, and bounded waits. Verify no cancelled callbacks execute and transferred peers close exactly once. Generic task cancellation remains #465; work-pool quiescence is #468.

9 days ago

Implemented and published in 41f10cb on codex/runtime-port (not merged into main). Chris Breuer is sole author and committer, no coauthors.

The native live-worker registry now propagates termination through descendants, including children registering during termination. Each parent waits for its direct children to finish exit-task publication and thread-local cleanup before destroying its VM. Only specifically marked native child-exit cleanup runs during parent shutdown; normal child exit still dispatches callbacks. Timeout of the main shutdown wait no longer authorizes freeing resources beneath live workers. Generic task cancellation and native producer quiescence remain #465 and #468, not silently considered complete.

Verification:

  • Build and cached rebuild 14/14; all 17 existing native runtime regression files pass.
  • Five native descendant cases pass on three consecutive runs, with an additional main-VM destruction run; two exact Node controls pass. The old Home binary failed the cancelled-child callback assertion.
  • Strict full-VM corpus: 15 pass, 3 upstream debug/sanitizer skips, 0 failures / 529 assertions. Three standalone upstream worker/transfer termination files pass.
  • 12 generator/ABI/source checks / 109 assertions; 4 Zig helper tests; focused Pickier and Zig formatting pass.

The expanded normal control exposed a separate parentPort.close() no-op, now #477 with an explicitly failing native regression and passing Node control. The descendant control uses a one-shot listener to isolate normal child exit; this does not count parentPort closure as implemented. #471 snapshot cancellation still fails. No full-suite or cross-platform completion is claimed. Detailed implementation and evidence are in docs/docs/NATIVE_RUNTIME_BINDINGS.md.

9 days ago

Follow-up to #477: published 3b0721c32b2d237c38380900ed449217ef1af853 supplies a real native parentPort lifecycle, so native-worker-nested-shutdown.test.mjs now again uses the original persistent .on("message") listener and parentPort.close() for natural exit. All five descendant scenarios pass twice in Home and once in the Node control. Main-VM destruction remains covered. This removes the earlier one-shot-listener workaround; publication is on codex/runtime-port, not merged into main. Overall tracking #66; separate remaining shutdown issues #465, #468, #471.

9 days ago

Integrated status verified on main at b4ddf30. The original implementation commits 41f10cb and 3b0721c are both ancestors of main. In the current ReleaseFast installation-shaped runtime, tests/runtime/native-worker-nested-shutdown.test.mjs passes all five scenarios: queued nested transfer cancellation, normal exit, process.exit, natural unref, and three-level branch/sibling termination. No callback suppression workaround or weakened deadline was added. Closing the stale integration tracker; generic native task auditing remains #465.

Sign in to comment on this issue.