| ... | @@ -993,6 +993,8 @@ fn write(buf: []const u8) anyerror!void { | ... | @@ -993,6 +993,8 @@ fn write(buf: []const u8) anyerror!void { |
| 993 | global_progress.written_newline_count = global_progress.accumulated_newline_count; | 993 | global_progress.written_newline_count = global_progress.accumulated_newline_count; |
| 994 | } | 994 | } |
| 995 | | 995 | |
| | 996 | var remaining_write_trash_bytes: usize = 0; |
| | 997 | |
| 996 | fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { | 998 | fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { |
| 997 | // Byteswap if necessary to ensure little endian over the pipe. This is | 999 | // Byteswap if necessary to ensure little endian over the pipe. This is |
| 998 | // needed because the parent or child process might be running in qemu. | 1000 | // 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 { | ... | @@ -1004,18 +1006,35 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { |
| 1004 | const storage = std.mem.sliceAsBytes(serialized.storage); | 1006 | const storage = std.mem.sliceAsBytes(serialized.storage); |
| 1005 | const parents = std.mem.sliceAsBytes(serialized.parents); | 1007 | const parents = std.mem.sliceAsBytes(serialized.parents); |
| 1006 | | 1008 | |
| 1007 | var vecs: [3]std.posix.iovec_const = .{ | 1009 | var vecs: [3]posix.iovec_const = .{ |
| 1008 | .{ .base = header.ptr, .len = header.len }, | 1010 | .{ .base = header.ptr, .len = header.len }, |
| 1009 | .{ .base = storage.ptr, .len = storage.len }, | 1011 | .{ .base = storage.ptr, .len = storage.len }, |
| 1010 | .{ .base = parents.ptr, .len = parents.len }, | 1012 | .{ .base = parents.ptr, .len = parents.len }, |
| 1011 | }; | 1013 | }; |
| 1012 | | 1014 | |
| | 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 | |
| 1013 | // If this write would block we do not want to keep trying, but we need to | 1032 | // If this write would block we do not want to keep trying, but we need to |
| 1014 | // know if a partial message was written. | 1033 | // know if a partial message was written. |
| 1015 | if (posix.writev(fd, &vecs)) |written| { | 1034 | if (posix.writev(fd, &vecs)) |written| { |
| 1016 | const total = header.len + storage.len + parents.len; | 1035 | const total = header.len + storage.len + parents.len; |
| 1017 | if (written < total) { | 1036 | if (written < total) { |
| 1018 | std.log.debug("short write: {d} out of {d}", .{ written, total }); | 1037 | remaining_write_trash_bytes = total - written; |
| 1019 | } | 1038 | } |
| 1020 | } else |err| switch (err) { | 1039 | } else |err| switch (err) { |
| 1021 | error.WouldBlock => {}, | 1040 | error.WouldBlock => {}, |