aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2020-10-21 16:54:38 +0200
committerJonathan Marler <johnnymarler@gmail.com>2021-06-17 17:39:32 -0600
commitb590195222ba560b8201f2344d7fcb398a43a504 (patch)
treebe2a085b494c332bc39fed18414f229120661bb9 /lib
parent34c00ecf57a50e19b31fce420044311c4f2e9c7a (diff)
downloadzig-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.zig49
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()) {