Follow-up to #4914, which ships worker port-sharing via SO_REUSEPORT (kernel-balanced, effectively SCHED_NONE). Two Node-fidelity items were consciously scoped out of that PR:
1. listen(0) — all workers must share ONE primary-assigned ephemeral port
In Node, when a cluster worker calls server.listen(0), the primary binds the ephemeral port once and every worker shares it. With the naive SO_REUSEPORT approach each worker binds its own ephemeral port, so N workers end up on N different ports.
Closing this needs a queryServer-style round-trip over the existing internal NODE_CLUSTER IPC message channel (consume_internal_message in crates/perry-runtime/src/cluster.rs): worker asks primary for the address key, primary binds (or returns the already-bound port), worker then binds that concrete port with SO_REUSEPORT.
2. SCHED_RR — true round-robin handle distribution via fd-passing
Node's default scheduling policy on non-Windows is round-robin: the primary owns the listening socket, accepts connections, and passes each accepted fd to a worker. Perry's fork IPC channel is already a socketpair(2) (UnixStream::pair() in crates/perry-runtime/src/child_process/fork.rs), so SCM_RIGHTS fd-passing is feasible — but it requires a primary-side accept loop, ancillary-data send/recv on the IPC channel, and reconstructing the connection inside the worker's HTTP/net server.
Until then cluster.schedulingPolicy reads as SCHED_RR but actual distribution is kernel SO_REUSEPORT balancing.
Acceptance
Follow-up to #4914, which ships worker port-sharing via SO_REUSEPORT (kernel-balanced, effectively
SCHED_NONE). Two Node-fidelity items were consciously scoped out of that PR:1.
listen(0)— all workers must share ONE primary-assigned ephemeral portIn Node, when a cluster worker calls
server.listen(0), the primary binds the ephemeral port once and every worker shares it. With the naive SO_REUSEPORT approach each worker binds its own ephemeral port, so N workers end up on N different ports.Closing this needs a
queryServer-style round-trip over the existing internalNODE_CLUSTERIPC message channel (consume_internal_messageincrates/perry-runtime/src/cluster.rs): worker asks primary for the address key, primary binds (or returns the already-bound port), worker then binds that concrete port with SO_REUSEPORT.2.
SCHED_RR— true round-robin handle distribution via fd-passingNode's default scheduling policy on non-Windows is round-robin: the primary owns the listening socket, accepts connections, and passes each accepted fd to a worker. Perry's fork IPC channel is already a
socketpair(2)(UnixStream::pair()incrates/perry-runtime/src/child_process/fork.rs), soSCM_RIGHTSfd-passing is feasible — but it requires a primary-side accept loop, ancillary-data send/recv on the IPC channel, and reconstructing the connection inside the worker's HTTP/net server.Until then
cluster.schedulingPolicyreads asSCHED_RRbut actual distribution is kernel SO_REUSEPORT balancing.Acceptance
listen(0)in N workers → all workers report the sameserver.address().port, primary-coordinated.SCHED_RRpolicy actually distributes accepted connections round-robin via fd-passing over the fork IPC socketpair.cluster.schedulingPolicy = cluster.SCHED_NONEvsSCHED_RRselects between the two mechanisms.