authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-10-21 16:54:38+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-29 10:40:00-07:00
log1667c937a0869cc266ce43b4ecbde4ad49ca23c5
tree37072911edf7cd42a3d0c0ef8fe7746ffd171c56
parent2c16a9668632be83c5e1bb0baeb00d221bb0eca1

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
......@@ -225,11 +225,11 @@ pub const ChildProcess = struct {
225225 }
226226
227227 fn collectOutputWindows(child: *const ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void {
228 // The order of the objects here is important, WaitForMultipleObjects
229 // uses the same order when scanning the events.
230228 var wait_objects = [_]windows.kernel32.HANDLE{
231 child.handle, child.stdout.?.handle, child.stderr.?.handle,
229 child.stdout.?.handle, child.stderr.?.handle,
232230 };
231 var waiting_objects: u32 = wait_objects.len;
232
233233 // XXX: Calling zeroes([2]windows.OVERLAPPED) causes the stage1 compiler
234234 // to crash and burn.
235235 var overlapped = [_]windows.OVERLAPPED{
......@@ -241,38 +241,31 @@ pub const ChildProcess = struct {
241241 // Kickstart the loop by issuing two async reads.
242242 // ReadFile returns false and GetLastError returns ERROR_IO_PENDING if
243243 // everything is ok.
244 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);
245 _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
244 _ = windows.kernel32.ReadFile(wait_objects[0], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);
245 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
246246
247 while (true) {
248 const status = windows.kernel32.WaitForMultipleObjects(wait_objects.len, &wait_objects, 0, windows.INFINITE);
249 std.debug.print("status {x}\n", .{status});
247 poll: while (waiting_objects > 0) {
248 const status = windows.kernel32.WaitForMultipleObjects(waiting_objects, &wait_objects, 0, windows.INFINITE);
250249 switch (status) {
251 windows.WAIT_OBJECT_0 + 0 => {
252 // The child process was terminated.
253 break;
254 },
255 windows.WAIT_OBJECT_0 + 1 => {
256 // stdout is ready.
257 var read_bytes: u32 = undefined;
258 if (windows.kernel32.GetOverlappedResult(wait_objects[1], &overlapped[0], &read_bytes, 0) == 0) {
259 switch (windows.kernel32.GetLastError()) {
260 else => |err| return windows.unexpectedError(err),
261 }
262 }
263 try stdout.appendSlice(temp_buf[0][0..read_bytes]);
264 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);
265 },
266 windows.WAIT_OBJECT_0 + 2 => {
267 // stderr is ready.
250 windows.WAIT_OBJECT_0 + 0...windows.WAIT_OBJECT_0 + 1 => {
251 // stdout (or stderr) is ready.
252 const object = status - windows.WAIT_OBJECT_0;
253
268254 var read_bytes: u32 = undefined;
269 if (windows.kernel32.GetOverlappedResult(wait_objects[2], &overlapped[1], &read_bytes, 0) == 0) {
255 if (windows.kernel32.GetOverlappedResult(wait_objects[object], &overlapped[object], &read_bytes, 0) == 0) {
270256 switch (windows.kernel32.GetLastError()) {
257 .BROKEN_PIPE => {
258 // Move it to the end to remove it.
259 if (object != waiting_objects - 1)
260 mem.swap(windows.kernel32.HANDLE, &wait_objects[object], &wait_objects[waiting_objects - 1]);
261 waiting_objects -= 1;
262 continue :poll;
263 },
271264 else => |err| return windows.unexpectedError(err),
272265 }
273266 }
274 try stdout.appendSlice(temp_buf[1][0..read_bytes]);
275 _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
267 try stdout.appendSlice(temp_buf[object][0..read_bytes]);
268 _ = windows.kernel32.ReadFile(wait_objects[object], &temp_buf[object], temp_buf[object].len, null, &overlapped[object]);
276269 },
277270 windows.WAIT_FAILED => {
278271 switch (windows.kernel32.GetLastError()) {