From eb05428c456092b2c2afc90c959fedbb3cab23ab Mon Sep 17 00:00:00 2001 From: Arshia Ghafoori Date: Mon, 6 Jul 2026 14:23:39 +0000 Subject: [PATCH] wasix: read IPC streams with plain read() instead of failing ENOSYS The IPC branch of uv__stream_io was stubbed to fail ENOSYS under __wasi__ (no msghdr support), which killed every Node child_process.fork / cluster.fork IPC channel on first readiness: the stream errored, libuv closed the fd, and subsequent sends failed EPIPE. No descriptor can accompany IPC data on WASIX anyway - uv__try_write already refuses send_handle with UV_ENOSYS on both ends - so a plain read() preserves the IPC byte stream exactly. This makes fork/process.send message channels fully functional under WASIX; passing handles (cluster round-robin connection distribution) remains unsupported. Co-Authored-By: Claude Fable 5 --- src/unix/stream.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index 1646dcb0a16..80dc407baab 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -1092,9 +1092,14 @@ static void uv__read(uv_stream_t* stream) { } while (nread < 0 && errno == EINTR); #else - /* WASI does not support msghdr. */ - nread = -1; - errno = ENOSYS; + /* WASIX has no msghdr/SCM_RIGHTS, so no descriptor can accompany the + * data (uv__try_write refuses send_handle with UV_ENOSYS on both + * ends). A plain read preserves the IPC byte stream, which is all + * that e.g. child_process.fork/process.send channels need. */ + do { + nread = read(uv__stream_fd(stream), buf.base, buf.len); + } + while (nread < 0 && errno == EINTR); #endif /* !__wasi__ */ }