diff options
| author | LemonBoy <thatlemon@gmail.com> | 2019-12-16 10:57:29 +0100 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2019-12-16 10:57:29 +0100 |
| commit | 9d9b0720f52059a5b18fdf313cb80fca6379e54d (patch) | |
| tree | 1dec8f0ebf41223a84ca251a6397886b61ed86cb /lib/std | |
| parent | c257f892fdeda9c738d4a3afdf80a12775269884 (diff) | |
| download | zig-9d9b0720f52059a5b18fdf313cb80fca6379e54d.tar.gz zig-9d9b0720f52059a5b18fdf313cb80fca6379e54d.zip | |
Fix for the error codepath in ChildProcess
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/child_process.zig | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index a7ca89c6a5..a76dfd3528 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -282,17 +282,36 @@ pub const ChildProcess = struct { fn cleanupAfterWait(self: *ChildProcess, status: u32) !Term { defer destroyPipe(self.err_pipe); - // Write maxInt(ErrInt) to the write end of the err_pipe. This is after - // waitpid, so this write is guaranteed to be after the child - // pid potentially wrote an error. This way we can do a blocking - // read on the error pipe and either get maxInt(ErrInt) (no error) or - // an error code. - try writeIntFd(self.err_pipe[1], maxInt(ErrInt)); - const err_int = try readIntFd(self.err_pipe[0]); - // Here we potentially return the fork child's error - // from the parent pid. - if (err_int != maxInt(ErrInt)) { - return @errSetCast(SpawnError, @intToError(err_int)); + if (builtin.os == .linux) { + var fd = [1]std.os.pollfd{std.os.pollfd{ + .fd = self.err_pipe[0], + .events = std.os.POLLIN, + .revents = undefined, + }}; + + // Check if the eventfd buffer stores a non-zero value by polling + // it, that's the error code returned by the child process. + _ = std.os.poll(&fd, 0) catch unreachable; + + // According to eventfd(2) the descriptro is readable if the counter + // has a value greater than 0 + if ((fd[0].revents & std.os.POLLIN) != 0) { + const err_int = try readIntFd(self.err_pipe[0]); + return @errSetCast(SpawnError, @intToError(err_int)); + } + } else { + // Write maxInt(ErrInt) to the write end of the err_pipe. This is after + // waitpid, so this write is guaranteed to be after the child + // pid potentially wrote an error. This way we can do a blocking + // read on the error pipe and either get maxInt(ErrInt) (no error) or + // an error code. + try writeIntFd(self.err_pipe[1], maxInt(ErrInt)); + const err_int = try readIntFd(self.err_pipe[0]); + // Here we potentially return the fork child's error from the parent + // pid. + if (err_int != maxInt(ErrInt)) { + return @errSetCast(SpawnError, @intToError(err_int)); + } } return statusToTerm(status); |
