ReviewOS

home-lang/home

Enforce native corpus deadlines after child output pipes close

#723
Open chris opened this 9 days ago ·
9 days ago

Parent #66; related #703/#709/#722. Native macOS repair is implemented and verified in 61670c72b. This issue stays open for native Linux/Windows execution verification.

Root cause: runSpawnSyncCaptured applied the original deadline to pipe draining, then called child.wait(io) without a deadline. An actual child that closes both output streams but remains alive could therefore outlive its original bound. The first fs.closeSync control did not reproduce this because pinned Bun/Home intentionally leave standard descriptors open in that API. The correct control uses Home's real FFI to call libc close; both calls return 0. Before the fix, the 20-second Node deadline was missed and the 30-second supervisor stopped the runner (124). Original first-run evidence is retained in 3f956ba.

Repair: observe exit without reaping (WNOWAIT on Darwin/Linux, stable process-handle observation on Windows); keep the same absolute deadline after EOF; terminate at expiration and preserve final ownership/resource/exit-status cleanup. The companion schema-2 journal now records whether streams reached complete EOF.

Verified: native build 23/23, native corpus harness 12/12, focused child units 2/2, journal units 3/3, validator units 9/9, targeted Pickier. Production libc-FFI early exit succeeds; the hanging closed-pipe child now receives the native timeout at the unchanged 20,000 ms deadline (20.47s observed including startup/cleanup), without the outer supervisor firing. Open-pipe timeout, SIGTERM, interruption, failed-write, mixed-case and invalid-negative regressions pass. Six original files retain 402 passes/1 skip/10 TODOs plus distinct process/empty outcomes, with source/snapshot/executable integrity unchanged. Final evidence. Verified Home fd7c61bf96b18d6954687cd33eb95e429290007f5d199fb985d364e868eb98c4.

The helper also compiles for x86_64-linux-musl and x86_64-windows-gnu with its exported call path instantiated. These are compile checks, not native execution. Run the real lifetime, timeout, capture and ownership controls on native Linux and Windows before closing this cross-platform issue. Full applicable primary/vendor corpus execution remains in #722/#724; overall parity remains incomplete in #66.

9 days ago

First real control does not reproduce the suspected gap. With verified Home d53d30234990213f93cc0460546cab369f97cf031be1dc9f036d4c21d39900d4 (runtime 719d636), the generated Node fixture writes its readiness/PID file, closes descriptors 1 and 2, and remains alive via an interval. Home records the original 20,000 ms deadline, a completed native timeout, and a failed file after 20.37 seconds. The 30-second diagnostic supervisor did not trigger. Source and executable hashes are unchanged.

This establishes correct deadline behavior for that control, not that the post-EOF child-wait path was exercised: inherited/duplicated pipe writers may still prevent EOF after only descriptors 1 and 2 close. The source-level unbounded child.wait(io) remains to investigate. Next reproduce actual EOF at the parent while the child is still alive, inspect pipe ownership, and only then repair a demonstrated lifetime gap. Do not count this control as a failing feature or claim the suspected gap confirmed.

Sign in to comment on this issue.