Repository navigation
Description
Summary
Perry still needs the child-side process IPC surface when a compiled Perry program is launched with a Node-style IPC channel (NODE_CHANNEL_FD).
The parent-side child_process.fork() IPC work landed in #1955/#1933, but that PR explicitly called out the compiled-Perry child side as a remaining follow-up. Today the lowering path appears to treat process.send, process.disconnect, and process.connected as unconditionally undefined, which matches a normal non-IPC process but cannot support a Perry child process inheriting fd 3.
Evidence
docs/runtime-parity.md:2275-2279listsprocess.send,process.disconnect,process.channel,process.channel.ref(), andprocess.channel.unref()as public Node process IPC APIs.docs/runtime-parity-gaps.md:635-639keeps the same process IPC rows in the gap list.crates/perry-hir/src/lower/expr_member.rsshort-circuitsprocess.send,process.disconnect, andprocess.connectedtoundefinedfor ordinary process member reads.crates/perry-runtime/src/child_process/fork.rslaunches forked children withNODE_CHANNEL_FD=3so Node children getprocess.send/process.on("message")automatically, but this does not install the same surface for a compiled Perry child.- PR feat(node:child_process): async spawn reactor, fork()+IPC, exec error/encoding parity (#1933–#1938) #1955 says the remaining follow-up is the child-side
process.send/process.on('message')behavior when a compiled-Perry binary is itself the fork target.
Expected behavior
When a Perry process starts with a valid Node-style IPC channel, it should expose Node-compatible child-side IPC APIs:
process.send(message[, sendHandle[, options]][, callback])serializes messages to the parent.process.on("message", handler)receives parent messages.process.disconnect()closes the IPC channel and updates state.process.connectedreflects channel state.process.channelexposes the channel object, includingref()/unref().- In a normal non-IPC process, these members should continue to match Node's non-IPC shape.
Duplicate check
I searched issues and PRs for compiled Perry child process.send NODE_CHANNEL_FD process.on message and process.send NODE_CHANNEL_FD process.channel compiled. The only related result is merged PR #1955 / closed #1933 for parent-side child_process.fork() IPC, and that PR explicitly leaves this compiled-child-side behavior as follow-up work.
Verification note
I do not have a local perry binary in this checkout, so this is based on committed parity docs/tests, source search, and the #1955 PR notes rather than a fresh runtime comparison.
Activity
andrewtdiz commentedon Jun 3, 2026
I’m taking this as a focused
node:processchild-side IPC parity cut.Intended PR scope: detect an inherited
NODE_CHANNEL_FDchannel in a compiled Perry child, expose the IPC-onlyprocess.send,process.disconnect,process.connected, andprocess.channelsurface only while that channel exists, deliver JSON IPC messages throughprocess.on("message"), and coverprocess.channel.ref()/unref()shape/active-handle behavior at a deterministic level.Non-goals: socket/handle passing,
serialization: "advanced"child-side framing, broad parent-sidechild_process.fork()changes, and unrelated process APIs.andrewtdiz commentedon Jun 3, 2026
Draft PR opened for this child-side IPC cut: #4207