authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-10-21 16:54:38+02:00
committergravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2021-06-17 17:39:32-06:00
logb590195222ba560b8201f2344d7fcb398a43a504
treebe2a085b494c332bc39fed18414f229120661bb9
parent34c00ecf57a50e19b31fce420044311c4f2e9c7a

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.

1 files changed, 21 insertions(+), 28 deletions(-)

lib/std/child_process.zig+21-28
......@@ -258,11 +258,11 @@ pub const ChildProcess = struct {
258258 }
259259
260260 fn collectOutputWindows(child: *const ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void {
261 // The order of the objects here is important, WaitForMultipleObjects
262 // uses the same order when scanning the events.
263261 var wait_objects = [_]windows.kernel32.HANDLE{
264 child.handle, child.stdout.?.handle, child.stderr.?.handle,
262 child.stdout.?.handle, child.stderr.?.handle,
265263 };
264 var waiting_objects: u32 = wait_objects.len;
265
266266 // XXX: Calling zeroes([2]windows.OVERLAPPED) causes the stage1 compiler
267267 // to crash and burn.
268268 var overlapped = [_]windows.OVERLAPPED{
......@@ -274,38 +274,31 @@ pub const ChildProcess = struct {
274274 // Kickstart the loop by issuing two async reads.
275275 // ReadFile returns false and GetLastError returns ERROR_IO_PENDING if
276276 // everything is ok.
277 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);
278 _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
277 _ = windows.kernel32.ReadFile(wait_objects[0], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);
278 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
279279
280 while (true) {
281 const status = windows.kernel32.WaitForMultipleObjects(wait_objects.len, &wait_objects, 0, windows.INFINITE);
282 std.debug.print("status {x}\n", .{status});
280 poll: while (waiting_objects > 0) {
281 const status = windows.kernel32.WaitForMultipleObjects(waiting_objects, &wait_objects, 0, windows.INFINITE);
283282 switch (status) {
284 windows.WAIT_OBJECT_0 + 0 => {
285 // The child process was terminated.
286 break;
287 },
288 windows.WAIT_OBJECT_0 + 1 => {
289 // stdout is ready.
290 var read_bytes: u32 = undefined;
291 if (windows.kernel32.GetOverlappedResult(wait_objects[1], &overlapped[0], &read_bytes, 0) == 0) {
292 switch (windows.kernel32.GetLastError()) {
293 else => |err| return windows.unexpectedError(err),
294 }
295 }
296 try stdout.appendSlice(temp_buf[0][0..read_bytes]);
297 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);
298 },
299 windows.WAIT_OBJECT_0 + 2 => {
300 // stderr is ready.
283 windows.WAIT_OBJECT_0 + 0...windows.WAIT_OBJECT_0 + 1 => {
284 // stdout (or stderr) is ready.
285 const object = status - windows.WAIT_OBJECT_0;
286
301287 var read_bytes: u32 = undefined;
302 if (windows.kernel32.GetOverlappedResult(wait_objects[2], &overlapped[1], &read_bytes, 0) == 0) {
288 if (windows.kernel32.GetOverlappedResult(wait_objects[object], &overlapped[object], &read_bytes, 0) == 0) {
303289 switch (windows.kernel32.GetLastError()) {
290 .BROKEN_PIPE => {
291 // Move it to the end to remove it.
292 if (object != waiting_objects - 1)
293 mem.swap(windows.kernel32.HANDLE, &wait_objects[object], &wait_objects[waiting_objects - 1]);
294 waiting_objects -= 1;
295 continue :poll;
296 },
304297 else => |err| return windows.unexpectedError(err),
305298 }
306299 }
307 try stdout.appendSlice(temp_buf[1][0..read_bytes]);
308 _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
300 try stdout.appendSlice(temp_buf[object][0..read_bytes]);
301 _ = windows.kernel32.ReadFile(wait_objects[object], &temp_buf[object], temp_buf[object].len, null, &overlapped[object]);
309302 },
310303 windows.WAIT_FAILED => {
311304 switch (windows.kernel32.GetLastError()) {