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 {...@@ -225,11 +225,11 @@ pub const ChildProcess = struct {
225 }225 }
226226
227 fn collectOutputWindows(child: *const ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void {227 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.
230 var wait_objects = [_]windows.kernel32.HANDLE{228 var wait_objects = [_]windows.kernel32.HANDLE{
231 child.handle, child.stdout.?.handle, child.stderr.?.handle,229 child.stdout.?.handle, child.stderr.?.handle,
232 };230 };
231 var waiting_objects: u32 = wait_objects.len;
232
233 // XXX: Calling zeroes([2]windows.OVERLAPPED) causes the stage1 compiler233 // XXX: Calling zeroes([2]windows.OVERLAPPED) causes the stage1 compiler
234 // to crash and burn.234 // to crash and burn.
235 var overlapped = [_]windows.OVERLAPPED{235 var overlapped = [_]windows.OVERLAPPED{
...@@ -241,38 +241,31 @@ pub const ChildProcess = struct {...@@ -241,38 +241,31 @@ pub const ChildProcess = struct {
241 // Kickstart the loop by issuing two async reads.241 // Kickstart the loop by issuing two async reads.
242 // ReadFile returns false and GetLastError returns ERROR_IO_PENDING if242 // ReadFile returns false and GetLastError returns ERROR_IO_PENDING if
243 // everything is ok.243 // everything is ok.
244 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[0], temp_buf[0].len, null, &overlapped[0]);244 _ = windows.kernel32.ReadFile(wait_objects[0], &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]);245 _ = windows.kernel32.ReadFile(wait_objects[1], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);
246246
247 while (true) {247 poll: while (waiting_objects > 0) {
248 const status = windows.kernel32.WaitForMultipleObjects(wait_objects.len, &wait_objects, 0, windows.INFINITE);248 const status = windows.kernel32.WaitForMultipleObjects(waiting_objects, &wait_objects, 0, windows.INFINITE);
249 std.debug.print("status {x}\n", .{status});
250 switch (status) {249 switch (status) {
251 windows.WAIT_OBJECT_0 + 0 => {250 windows.WAIT_OBJECT_0 + 0...windows.WAIT_OBJECT_0 + 1 => {
252 // The child process was terminated.251 // stdout (or stderr) is ready.
253 break;252 const object = status - windows.WAIT_OBJECT_0;
254 },253
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.
268 var read_bytes: u32 = undefined;254 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) {
270 switch (windows.kernel32.GetLastError()) {256 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 },
271 else => |err| return windows.unexpectedError(err),264 else => |err| return windows.unexpectedError(err),
272 }265 }
273 }266 }
274 try stdout.appendSlice(temp_buf[1][0..read_bytes]);267 try stdout.appendSlice(temp_buf[object][0..read_bytes]);
275 _ = windows.kernel32.ReadFile(wait_objects[2], &temp_buf[1], temp_buf[1].len, null, &overlapped[1]);268 _ = windows.kernel32.ReadFile(wait_objects[object], &temp_buf[object], temp_buf[object].len, null, &overlapped[object]);
276 },269 },
277 windows.WAIT_FAILED => {270 windows.WAIT_FAILED => {
278 switch (windows.kernel32.GetLastError()) {271 switch (windows.kernel32.GetLastError()) {