authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2022-02-05 18:59:09-07:00
committergravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2022-02-06 18:05:20-07:00
log53d8a25dab5ddcea16ac70cdcdf28cb3e4944cbb
tree15fd1fa33b9657dc8ed2eaa233333c28551b6a31
parentadc9a282d8b3cbe58e07c965fe40fb1dd8666bd7

child_process: collectOutputWindows handle broken_pipe from ReadFile

This was found on a user's machine when calling "git" as a child process from msys. Instead of getting BROKEN_PIPE on GetOverlappedREsult, it would occur on ReadFile which would then cause the function to hang because the async operation was never started.

1 files changed, 22 insertions(+), 6 deletions(-)

lib/std/child_process.zig+22-6
...@@ -277,10 +277,19 @@ pub const ChildProcess = struct {...@@ -277,10 +277,19 @@ pub const ChildProcess = struct {
277 const new_capacity = std.math.min(outs[i].items.len + bump_amt, max_output_bytes);277 const new_capacity = std.math.min(outs[i].items.len + bump_amt, max_output_bytes);
278 try outs[i].ensureTotalCapacity(new_capacity);278 try outs[i].ensureTotalCapacity(new_capacity);
279 const buf = outs[i].unusedCapacitySlice();279 const buf = outs[i].unusedCapacitySlice();
280 _ = windows.kernel32.ReadFile(handles[i], buf.ptr, math.cast(u32, buf.len) catch maxInt(u32), null, &overlapped[i]);280 const read_result = windows.kernel32.ReadFile(handles[i], buf.ptr, math.cast(u32, buf.len) catch maxInt(u32), null, &overlapped[i]);
281 wait_objects[wait_object_count] = handles[i];281 std.debug.assert(read_result == 0);
282 wait_object_count += 1;282 switch (windows.kernel32.GetLastError()) {
283 .IO_PENDING => {
284 wait_objects[wait_object_count] = handles[i];
285 wait_object_count += 1;
286 },
287 .BROKEN_PIPE => {}, // don't add to the wait_objects list
288 else => |err| return windows.unexpectedError(err),
289 }
283 }290 }
291 if (wait_object_count == 0)
292 return;
284293
285 while (true) {294 while (true) {
286 const status = windows.kernel32.WaitForMultipleObjects(wait_object_count, &wait_objects, 0, windows.INFINITE);295 const status = windows.kernel32.WaitForMultipleObjects(wait_object_count, &wait_objects, 0, windows.INFINITE);
...@@ -320,9 +329,16 @@ pub const ChildProcess = struct {...@@ -320,9 +329,16 @@ pub const ChildProcess = struct {
320 try outs[i].ensureTotalCapacity(new_capacity);329 try outs[i].ensureTotalCapacity(new_capacity);
321 const buf = outs[i].unusedCapacitySlice();330 const buf = outs[i].unusedCapacitySlice();
322 if (buf.len == 0) return if (i == 0) error.StdoutStreamTooLong else error.StderrStreamTooLong;331 if (buf.len == 0) return if (i == 0) error.StdoutStreamTooLong else error.StderrStreamTooLong;
323 _ = windows.kernel32.ReadFile(handles[i], buf.ptr, math.cast(u32, buf.len) catch maxInt(u32), null, &overlapped[i]);332 const read_result = windows.kernel32.ReadFile(handles[i], buf.ptr, math.cast(u32, buf.len) catch maxInt(u32), null, &overlapped[i]);
324 wait_objects[wait_object_count] = handles[i];333 std.debug.assert(read_result == 0);
325 wait_object_count += 1;334 switch (windows.kernel32.GetLastError()) {
335 .IO_PENDING => {
336 wait_objects[wait_object_count] = handles[i];
337 wait_object_count += 1;
338 },
339 .BROKEN_PIPE => {}, // don't add to the wait_objects list
340 else => |err| return windows.unexpectedError(err),
341 }
326 }342 }
327 }343 }
328344