Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions lib/std/process/Child.zig
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,18 @@ fn statusToTerm(status: u32) Term {
}

fn spawnPosix(self: *ChildProcess) SpawnError!void {
const pipe_flags: posix.O = .{};
// The child process does need to access (one end of) these pipes. However,
// we must initially set CLOEXEC to avoid a race condition. If another thread
// is racing to spawn a different child process, we don't want it to inherit
// these FDs in any scenario; that would mean that, for instance, calls to
// `poll` from the parent would not report the child's stdout as closing when
// expected, since the other child may retain a reference to the write end of
// the pipe. So, we create the pipes with CLOEXEC initially. After fork, we
// need to do something in the new child to make sure we preserve the reference
// we want. We could use `fcntl` to remove CLOEXEC from the FD, but as it
// turns out, we `dup2` everything anyway, so there's no need!
const pipe_flags: posix.O = .{ .CLOEXEC = true };

const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try posix.pipe2(pipe_flags) else undefined;
errdefer if (self.stdin_behavior == StdIo.Pipe) {
destroyPipe(stdin_pipe);
Expand Down Expand Up @@ -614,19 +625,6 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void {
setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);

if (self.stdin_behavior == .Pipe) {
posix.close(stdin_pipe[0]);
posix.close(stdin_pipe[1]);
}
if (self.stdout_behavior == .Pipe) {
posix.close(stdout_pipe[0]);
posix.close(stdout_pipe[1]);
}
if (self.stderr_behavior == .Pipe) {
posix.close(stderr_pipe[0]);
posix.close(stderr_pipe[1]);
}

if (self.cwd_dir) |cwd| {
posix.fchdir(cwd.fd) catch |err| forkChildErrReport(err_pipe[1], err);
} else if (self.cwd) |cwd| {
Expand Down