From 21839116ebc56b461914b7dd8dadff3f12423a8a Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Thu, 19 Mar 2026 16:56:45 +0000 Subject: [PATCH] syscall: Accept O_NONBLOCK flag in pipe2 pipe2 only accepted O_CLOEXEC, rejecting O_NONBLOCK with ENOTSUP. Accept O_NONBLOCK and set it on the created pipe streams. This is needed by GLib's GWakeup which uses pipe2(fds, O_CLOEXEC | O_NONBLOCK). --- src/lib/libsyscall.js | 8 +++++++- test/unistd/misc.c | 8 ++++++++ test/unistd/misc.out | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib/libsyscall.js b/src/lib/libsyscall.js index 1e1976cf41875..7fe77e016ecd5 100644 --- a/src/lib/libsyscall.js +++ b/src/lib/libsyscall.js @@ -199,12 +199,18 @@ var SyscallsLibrary = { if (fdPtr == 0) { throw new FS.ErrnoError({{{ cDefs.EFAULT }}}); } - if (flags && flags != {{{ cDefs.O_CLOEXEC }}}) { + var validFlags = {{{ cDefs.O_CLOEXEC }}} | {{{ cDefs.O_NONBLOCK }}}; + if (flags & ~validFlags) { throw new FS.ErrnoError({{{ cDefs.ENOTSUP }}}); } var res = PIPEFS.createPipe(); + if (flags & {{{ cDefs.O_NONBLOCK }}}) { + FS.getStream(res.readable_fd).flags |= {{{ cDefs.O_NONBLOCK }}}; + FS.getStream(res.writable_fd).flags |= {{{ cDefs.O_NONBLOCK }}}; + } + {{{ makeSetValue('fdPtr', 0, 'res.readable_fd', 'i32') }}}; {{{ makeSetValue('fdPtr', 4, 'res.writable_fd', 'i32') }}}; diff --git a/test/unistd/misc.c b/test/unistd/misc.c index 3efcbad477a63..190582957f200 100644 --- a/test/unistd/misc.c +++ b/test/unistd/misc.c @@ -86,6 +86,14 @@ int main() { printf("pipe2(bad): %d", pipe2(0, 0)); printf(", errno: %d\n", errno); errno = 0; + printf("pipe2(O_NONBLOCK): %d", pipe2(pipe_arg, O_NONBLOCK)); + printf(", errno: %d\n", errno); + printf("pipe2(O_NONBLOCK) read flags: %d\n", (fcntl(pipe_arg[0], F_GETFL) & O_NONBLOCK) != 0); + printf("pipe2(O_NONBLOCK) write flags: %d\n", (fcntl(pipe_arg[1], F_GETFL) & O_NONBLOCK) != 0); + errno = 0; + printf("pipe2(O_CLOEXEC|O_NONBLOCK): %d", pipe2(pipe_arg, O_CLOEXEC | O_NONBLOCK)); + printf(", errno: %d\n", errno); + errno = 0; char* exec_argv[] = {"arg", 0}; char* exec_env[] = {"a=b", 0}; diff --git a/test/unistd/misc.out b/test/unistd/misc.out index 17e5b17ffa0e5..4ed4b37a3b5fd 100644 --- a/test/unistd/misc.out +++ b/test/unistd/misc.out @@ -15,6 +15,10 @@ pipe(good): 0, errno: 0 pipe(bad): -1, errno: 21 pipe2(good): 0, errno: 0 pipe2(bad): -1, errno: 21 +pipe2(O_NONBLOCK): 0, errno: 0 +pipe2(O_NONBLOCK) read flags: 1 +pipe2(O_NONBLOCK) write flags: 1 +pipe2(O_CLOEXEC|O_NONBLOCK): 0, errno: 0 execl: -1, errno: 45 execle: -1, errno: 45 execlp: -1, errno: 45