authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 12:19:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 20:56:49-07:00
log2367a1ff846ef2f146d4f7e449044970d399046b
treec3dc18c77fc1b7c09f894b8c1d748b487eea18f7
parentdcf9cae2568a7422ab7885404da63fafa31b00fc

std.Progress: handle short writes


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

lib/std/Progress.zig+21-2
......@@ -993,6 +993,8 @@ fn write(buf: []const u8) anyerror!void {
993993 global_progress.written_newline_count = global_progress.accumulated_newline_count;
994994}
995995
996var remaining_write_trash_bytes: usize = 0;
997
996998fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
997999 // Byteswap if necessary to ensure little endian over the pipe. This is
9981000 // needed because the parent or child process might be running in qemu.
......@@ -1004,18 +1006,35 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
10041006 const storage = std.mem.sliceAsBytes(serialized.storage);
10051007 const parents = std.mem.sliceAsBytes(serialized.parents);
10061008
1007 var vecs: [3]std.posix.iovec_const = .{
1009 var vecs: [3]posix.iovec_const = .{
10081010 .{ .base = header.ptr, .len = header.len },
10091011 .{ .base = storage.ptr, .len = storage.len },
10101012 .{ .base = parents.ptr, .len = parents.len },
10111013 };
10121014
1015 while (remaining_write_trash_bytes > 0) {
1016 // We do this in a separate write call to give a better chance for the
1017 // writev below to be in a single packet.
1018 const n = @min(parents.len, remaining_write_trash_bytes);
1019 if (posix.write(fd, parents[0..n])) |written| {
1020 remaining_write_trash_bytes -= written;
1021 continue;
1022 } else |err| switch (err) {
1023 error.WouldBlock => return,
1024 error.BrokenPipe => return error.BrokenPipe,
1025 else => |e| {
1026 std.log.debug("failed to send progress to parent process: {s}", .{@errorName(e)});
1027 return error.BrokenPipe;
1028 },
1029 }
1030 }
1031
10131032 // If this write would block we do not want to keep trying, but we need to
10141033 // know if a partial message was written.
10151034 if (posix.writev(fd, &vecs)) |written| {
10161035 const total = header.len + storage.len + parents.len;
10171036 if (written < total) {
1018 std.log.debug("short write: {d} out of {d}", .{ written, total });
1037 remaining_write_trash_bytes = total - written;
10191038 }
10201039 } else |err| switch (err) {
10211040 error.WouldBlock => {},