diff options
| author | LemonBoy <thatlemon@gmail.com> | 2020-10-21 16:54:38 +0200 |
|---|---|---|
| committer | Jonathan Marler <johnnymarler@gmail.com> | 2021-06-17 17:39:32 -0600 |
| commit | b590195222ba560b8201f2344d7fcb398a43a504 (patch) | |
| tree | be2a085b494c332bc39fed18414f229120661bb9 /lib | |
| parent | 34c00ecf57a50e19b31fce420044311c4f2e9c7a (diff) | |
| download | zig-b590195222ba560b8201f2344d7fcb398a43a504.tar.gz zig-b590195222ba560b8201f2344d7fcb398a43a504.zip | |
std: Uniform polling logic for Windows and Unix
Keep polling until there are enough open handles, if the child process
terminates closing the handles or explicitly closes them we just quit
polling and wait for the process handle to signal the termination
condition.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/child_process.zig | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 936609d309..644a17c1dc 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -258,11 +258,11 @@ pub const ChildProcess = struct { } fn collectOutputWindows(child: *const ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void { - // The order of the objects here is important, WaitForMultipleObjects - // uses the same order when scanning the events. var wait_objects = [_]windows.kernel32.HANDLE{ - child.handle, child.stdout.?.handle, child.stderr.?.handle, + child.stdout.?.handle, child.stderr.?.handle, }; + var waiting_objects: u32 = wait_objects.len; + // XXX: Calling zeroes([2]windows.OVERLAPPED) causes the stage1 compiler // to crash and burn. var overlapped = [_]windows.OVERLAPPED{ @@ -274,38 +274,31 @@ pub const ChildProcess = struct { // Kickstart the loop by issuing two async reads. // ReadFile returns false and GetLastError returns ERROR_IO_PENDING if // everything is ok. - _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]); - _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]); + _ = windows.kernel32.ReadFile(wait_objects[0], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]); + _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]); - while (true) { - const status = windows.kernel32.WaitForMultipleObjects(wait_objects.len, &wait_objects, 0, windows.INFINITE); - std.debug.print("status {x}\n", .{status}); + poll: while (waiting_objects > 0) { + const status = windows.kernel32.WaitForMultipleObjects(waiting_objects, &wait_objects, 0, windows.INFINITE); switch (status) { - windows.WAIT_OBJECT_0 + 0 => { - // The child process was terminated. - break; - }, - windows.WAIT_OBJECT_0 + 1 => { - // stdout is ready. - var read_bytes: u32 = undefined; - if (windows.kernel32.GetOverlappedResult(wait_objects[1], &overlapped[0], &read_bytes, 0) == 0) { - switch (windows.kernel32.GetLastError()) { - else => |err| return windows.unexpectedError(err), - } - } - try stdout.appendSlice(temp_buf[0][0..read_bytes]); - _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]); - }, - windows.WAIT_OBJECT_0 + 2 => { - // stderr is ready. + windows.WAIT_OBJECT_0 + 0...windows.WAIT_OBJECT_0 + 1 => { + // stdout (or stderr) is ready. + const object = status - windows.WAIT_OBJECT_0; + var read_bytes: u32 = undefined; - if (windows.kernel32.GetOverlappedResult(wait_objects[2], &overlapped[1], &read_bytes, 0) == 0) { + if (windows.kernel32.GetOverlappedResult(wait_objects[object], &overlapped[object], &read_bytes, 0) == 0) { switch (windows.kernel32.GetLastError()) { + .BROKEN_PIPE => { + // Move it to the end to remove it. + if (object != waiting_objects - 1) + mem.swap(windows.kernel32.HANDLE, &wait_objects[object], &wait_objects[waiting_objects - 1]); + waiting_objects -= 1; + continue :poll; + }, else => |err| return windows.unexpectedError(err), } } - try stdout.appendSlice(temp_buf[1][0..read_bytes]); - _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]); + try stdout.appendSlice(temp_buf[object][0..read_bytes]); + _ = windows.kernel32.ReadFile(wait_objects[object], &temp_buf[object], temp_buf[object].len, null, &overlapped[object]); }, windows.WAIT_FAILED => { switch (windows.kernel32.GetLastError()) { |
