ReviewOS

home-lang/home

Native subprocess parity: support extra stdio pipes and their GC ownership

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

Follow-up to #66 and #493. During native POSIX spawn error verification, the unchanged packages/runtime/test/bun-corpus/js/node/child_process/child_process.test.ts regression extra stdio pipes are not double-closed on GC fails in Home. Its child calls spawn(process.execPath, ["-e", ""], { stdio: ["ignore", "ignore", "ignore", "pipe", "pipe", "pipe"] }), but Home rejects the array with ERR_INVALID_ARG_TYPE before executing the workload. Installed Bun 1.3.14 passes this case.

Port extra child_process stdio pipes through the real native spawn/stream implementation, retain exactly the requested sockets, and balance ownership through exit, explicit destroy and GC. Preserve the unchanged 20-round workload, delays, two GCs per round and final OK marker. Do not replace extra pipe entries, skip the case, or count argument rejection as lifecycle coverage.

The full child-process file currently reports 30 pass / 2 fail / 1 skip / 1 TODO / 70 assertions in Home after the #493 spawn errno patch. The other failure is the package-script stdio-passthrough scenario, tracked separately. Source pin: 4982b91e3702094330f3be3883354c52b8c01323. #493 fixes libc/setup error propagation, not extra-pipe creation.

9 days ago

Cross-reference update: #493 is implemented and verified in 6d797186c, with #66 updated. Extra stdio pipe creation/ownership remains unresolved; the unrelated native spawn setup errors are fixed. The other adjacent gaps are #495 (extra stdio), #496 (real counter snapshots), and #497 (package scripts). These remain separate from the passing full Node timer file (20 tests / 31 assertions).

9 days ago

Implemented on codex/runtime-port in a21f735fc; not merged into main.

The selected child_process builtin requests socket-fd, which the old native parser rejected. The port creates the real socketpair, preserves native ownership through fallible setup, then transfers only those slots to caller ownership immediately before returning the JS Subprocess. Standard stdio indices and spawnSync reject this mode; the latter cannot expose the fd. Windows maps to the upstream libuv path but has not been executed here.

The unchanged 20-round GC workload passes 1 test / 1 assertion (33 filtered cases excluded). The unchanged raw socket-fd selection passes 3 tests / 5 assertions (128 filtered out), including child writes, caller reads after exit and explicit caller close. Repeated missing-executable/invalid-later-fd native cases check cleanup of sockets that were never handed to JS. All 21 native files and the final 31-command regression batch pass; build and cached build are 17/17. The prior published binary still rejects the original extra-pipe workload.

Complete child-process result is now 31 pass / 1 fail / 1 skip / 1 TODO / 70 assertions; #497 is the remaining failure. Extra Blob/stream validation is separate in #499. Counter observability is #496. Keeping this open for integration and platform validation under #66; no full-suite claim.

9 days ago

Closing as integrated on main. The implementation commit a21f735 is an ancestor of current main. Fresh Darwin arm64 ReleaseFast verification passes the unchanged 20-round extra-stdio GC workload at 1/1 and the complete child-process file at 32 runnable passes / 72 assertions / 0 failures. The full unchanged spawn file also passes 126 tests / 5,484 assertions with its original lifecycle workload. Linux and Windows ownership verification is now tracked explicitly in #678; whole-suite parity remains #66.

Sign in to comment on this issue.