authorgravatar for breakmit@noreply.codeberg.orgbreakmit <breakmit@noreply.codeberg.org> 2026-03-06 04:51:28+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-06 04:51:28+01:00
log46658257f458b7c3c95d7e10cbde85403f7bdb44
treedcc40a21a71128f1abb936e6af006153d4905d33
parent30c8a759978c11620e90bf5117829c92c14bbf28

Io.Threaded.spawnPosix: implement passing file descriptors as stdio (#31379)

`std.process.spawn`: remove the TODO for nonblocking file stdio and document the behavior. Fix a bug in Io.Uring.dup2 where the function does not return on success Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31379 Reviewed-by: Andrew Kelley <andrew@ziglang.org> Co-authored-by: breakmit <breakmit@noreply.codeberg.org> Co-committed-by: breakmit <breakmit@noreply.codeberg.org>

4 files changed, 10 insertions(+), 10 deletions(-)

lib/std/Io/Dispatch.zig+1-4
...@@ -4404,10 +4404,7 @@ fn setUpChildIo(...@@ -4404,10 +4404,7 @@ fn setUpChildIo(
4404 .close => closeFd(std_fileno),4404 .close => closeFd(std_fileno),
4405 .inherit => {},4405 .inherit => {},
4406 .ignore => try ev.dup2(dev_null_fd, std_fileno),4406 .ignore => try ev.dup2(dev_null_fd, std_fileno),
4407 .file => |file| {4407 .file => |file| try ev.dup2(file.handle, std_fileno),
4408 if (file.flags.nonblocking) @panic("TODO implement setUpChildIo when nonblocking file is used");
4409 try ev.dup2(file.handle, std_fileno);
4410 },
4411 }4408 }
4412}4409}
44134410
lib/std/Io/Threaded.zig+1-1
...@@ -15659,7 +15659,7 @@ fn setUpChildIo(stdio: process.SpawnOptions.StdIo, pipe_fd: i32, std_fileno: i32...@@ -15659,7 +15659,7 @@ fn setUpChildIo(stdio: process.SpawnOptions.StdIo, pipe_fd: i32, std_fileno: i32
15659 .close => closeFd(std_fileno),15659 .close => closeFd(std_fileno),
15660 .inherit => {},15660 .inherit => {},
15661 .ignore => try dup2(dev_null_fd, std_fileno),15661 .ignore => try dup2(dev_null_fd, std_fileno),
15662 .file => @panic("TODO implement setUpChildIo when file is used"),15662 .file => |file| try dup2(file.handle, std_fileno),
15663 }15663 }
15664}15664}
1566515665
lib/std/Io/Uring.zig+2-5
...@@ -4550,10 +4550,7 @@ fn setUpChildIo(...@@ -4550,10 +4550,7 @@ fn setUpChildIo(
4550 .close => _ = linux.close(std_fileno),4550 .close => _ = linux.close(std_fileno),
4551 .inherit => {},4551 .inherit => {},
4552 .ignore => try dup2(sync, dev_null_fd, std_fileno),4552 .ignore => try dup2(sync, dev_null_fd, std_fileno),
4553 .file => |file| {4553 .file => |file| try dup2(sync, file.handle, std_fileno),
4554 if (file.flags.nonblocking) @panic("TODO implement setUpChildIo when nonblocking file is used");
4555 try dup2(sync, file.handle, std_fileno);
4556 },
4557 }4554 }
4558}4555}
45594556
...@@ -4565,7 +4562,7 @@ pub fn dup2(sync: *CancelRegion.Sync, old_fd: fd_t, new_fd: fd_t) DupError!void...@@ -4565,7 +4562,7 @@ pub fn dup2(sync: *CancelRegion.Sync, old_fd: fd_t, new_fd: fd_t) DupError!void
4565 while (true) {4562 while (true) {
4566 try sync.cancel_region.await(.nothing);4563 try sync.cancel_region.await(.nothing);
4567 switch (linux.errno(linux.dup2(old_fd, new_fd))) {4564 switch (linux.errno(linux.dup2(old_fd, new_fd))) {
4568 .SUCCESS => {},4565 .SUCCESS => return,
4569 .BUSY, .INTR => {},4566 .BUSY, .INTR => {},
4570 .INVAL => |err| return errnoBug(err), // invalid parameters4567 .INVAL => |err| return errnoBug(err), // invalid parameters
4571 .BADF => |err| return errnoBug(err), // use after free4568 .BADF => |err| return errnoBug(err), // use after free
lib/std/process.zig+6
...@@ -409,6 +409,12 @@ pub const SpawnOptions = struct {...@@ -409,6 +409,12 @@ pub const SpawnOptions = struct {
409 /// Inherit the corresponding stream from the parent process.409 /// Inherit the corresponding stream from the parent process.
410 inherit,410 inherit,
411 /// Pass an already open file from the parent to the child.411 /// Pass an already open file from the parent to the child.
412 ///
413 /// Nonblocking mode will be kept in the child process if present. This is
414 /// likely not supported by the child process. For example:
415 /// - Zig's std.Io.File.stdout() assumes blocking mode
416 /// - Rust explicity documents that nonblocking stdio may cause panics
417 /// - C++ standard streams do not support nonblocking file descriptors
412 file: File,418 file: File,
413 /// Pass a null stream to the child process by opening "/dev/null" on POSIX419 /// Pass a null stream to the child process by opening "/dev/null" on POSIX
414 /// and "NUL" on Windows.420 /// and "NUL" on Windows.