| ... | ... | @@ -526,7 +526,18 @@ fn statusToTerm(status: u32) Term { |
| 526 | 526 | } |
| 527 | 527 | |
| 528 | 528 | fn spawnPosix(self: *ChildProcess) SpawnError!void { |
| 529 | | const pipe_flags: posix.O = .{}; |
| 529 | // The child process does need to access (one end of) these pipes. However, |
| 530 | // we must initially set CLOEXEC to avoid a race condition. If another thread |
| 531 | // is racing to spawn a different child process, we don't want it to inherit |
| 532 | // these FDs in any scenario; that would mean that, for instance, calls to |
| 533 | // `poll` from the parent would not report the child's stdout as closing when |
| 534 | // expected, since the other child may retain a reference to the write end of |
| 535 | // the pipe. So, we create the pipes with CLOEXEC initially. After fork, we |
| 536 | // need to do something in the new child to make sure we preserve the reference |
| 537 | // we want. We could use `fcntl` to remove CLOEXEC from the FD, but as it |
| 538 | // turns out, we `dup2` everything anyway, so there's no need! |
| 539 | const pipe_flags: posix.O = .{ .CLOEXEC = true }; |
| 540 | |
| 530 | 541 | const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try posix.pipe2(pipe_flags) else undefined; |
| 531 | 542 | errdefer if (self.stdin_behavior == StdIo.Pipe) { |
| 532 | 543 | destroyPipe(stdin_pipe); |
| ... | ... | @@ -614,19 +625,6 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void { |
| 614 | 625 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 615 | 626 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 616 | 627 | |
| 617 | | if (self.stdin_behavior == .Pipe) { |
| 618 | | posix.close(stdin_pipe[0]); |
| 619 | | posix.close(stdin_pipe[1]); |
| 620 | | } |
| 621 | | if (self.stdout_behavior == .Pipe) { |
| 622 | | posix.close(stdout_pipe[0]); |
| 623 | | posix.close(stdout_pipe[1]); |
| 624 | | } |
| 625 | | if (self.stderr_behavior == .Pipe) { |
| 626 | | posix.close(stderr_pipe[0]); |
| 627 | | posix.close(stderr_pipe[1]); |
| 628 | | } |
| 629 | | |
| 630 | 628 | if (self.cwd_dir) |cwd| { |
| 631 | 629 | posix.fchdir(cwd.fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 632 | 630 | } else if (self.cwd) |cwd| { |