Commit 9d9b0720f5
Changed files (1)
lib
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);