authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-12-16 10:57:29+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-12-16 10:57:29+01:00
log9d9b0720f52059a5b18fdf313cb80fca6379e54d
tree1dec8f0ebf41223a84ca251a6397886b61ed86cb
parentc257f892fdeda9c738d4a3afdf80a12775269884

Fix for the error codepath in ChildProcess


1 files changed, 30 insertions(+), 11 deletions(-)

lib/std/child_process.zig+30-11
......@@ -282,17 +282,36 @@ pub const ChildProcess = struct {
282282 fn cleanupAfterWait(self: *ChildProcess, status: u32) !Term {
283283 defer destroyPipe(self.err_pipe);
284284
285 // Write maxInt(ErrInt) to the write end of the err_pipe. This is after
286 // waitpid, so this write is guaranteed to be after the child
287 // pid potentially wrote an error. This way we can do a blocking
288 // read on the error pipe and either get maxInt(ErrInt) (no error) or
289 // an error code.
290 try writeIntFd(self.err_pipe[1], maxInt(ErrInt));
291 const err_int = try readIntFd(self.err_pipe[0]);
292 // Here we potentially return the fork child's error
293 // from the parent pid.
294 if (err_int != maxInt(ErrInt)) {
295 return @errSetCast(SpawnError, @intToError(err_int));
285 if (builtin.os == .linux) {
286 var fd = [1]std.os.pollfd{std.os.pollfd{
287 .fd = self.err_pipe[0],
288 .events = std.os.POLLIN,
289 .revents = undefined,
290 }};
291
292 // Check if the eventfd buffer stores a non-zero value by polling
293 // it, that's the error code returned by the child process.
294 _ = std.os.poll(&fd, 0) catch unreachable;
295
296 // According to eventfd(2) the descriptro is readable if the counter
297 // has a value greater than 0
298 if ((fd[0].revents & std.os.POLLIN) != 0) {
299 const err_int = try readIntFd(self.err_pipe[0]);
300 return @errSetCast(SpawnError, @intToError(err_int));
301 }
302 } else {
303 // Write maxInt(ErrInt) to the write end of the err_pipe. This is after
304 // waitpid, so this write is guaranteed to be after the child
305 // pid potentially wrote an error. This way we can do a blocking
306 // read on the error pipe and either get maxInt(ErrInt) (no error) or
307 // an error code.
308 try writeIntFd(self.err_pipe[1], maxInt(ErrInt));
309 const err_int = try readIntFd(self.err_pipe[0]);
310 // Here we potentially return the fork child's error from the parent
311 // pid.
312 if (err_int != maxInt(ErrInt)) {
313 return @errSetCast(SpawnError, @intToError(err_int));
314 }
296315 }
297316
298317 return statusToTerm(status);