authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-19 15:14:43-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 22:03:14-08:00
logec74d650fe5ba6b5fddd0277b06b43a94383a0e0
tree272dab0920d49d1ab468588918250bd171fbf08c
parenta901ea23b0a53f6feba0111886156262fcff469d

incr-check: update to std.Io.File.MultiReader

from std.Io.poll

1 files changed, 45 insertions(+), 37 deletions(-)

tools/incr-check.zig+45-37
......@@ -28,6 +28,7 @@ fn logImpl(
2828}
2929
3030pub fn main(init: std.process.Init) !void {
31 const gpa = init.gpa;
3132 const fatal = std.process.fatal;
3233 const arena = init.arena.allocator();
3334 const io = init.io;
......@@ -224,11 +225,10 @@ pub fn main(init: std.process.Init) !void {
224225 .enable_darling = enable_darling,
225226 };
226227
227 var poller = Io.poll(arena, Eval.StreamEnum, .{
228 .stdout = child.stdout.?,
229 .stderr = child.stderr.?,
230 });
231 defer poller.deinit();
228 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;
229 var multi_reader: Io.File.MultiReader = undefined;
230 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
231 defer multi_reader.deinit();
232232
233233 for (case.updates) |update| {
234234 var update_node = target_prog_node.start(update.name, 0);
......@@ -243,10 +243,10 @@ pub fn main(init: std.process.Init) !void {
243243
244244 eval.write(update);
245245 try eval.requestUpdate();
246 try eval.check(&poller, update, update_node);
246 try eval.check(&multi_reader, update, update_node);
247247 }
248248
249 try eval.end(&poller);
249 try eval.end(&multi_reader);
250250
251251 waitChild(&child, &eval);
252252 }
......@@ -272,9 +272,6 @@ const Eval = struct {
272272 enable_wasmtime: bool,
273273 enable_darling: bool,
274274
275 const StreamEnum = enum { stdout, stderr };
276 const Poller = Io.Poller(StreamEnum);
277
278275 /// Currently this function assumes the previous updates have already been written.
279276 fn write(eval: *Eval, update: Case.Update) void {
280277 const io = eval.io;
......@@ -293,23 +290,29 @@ const Eval = struct {
293290 }
294291 }
295292
296 fn check(eval: *Eval, poller: *Poller, update: Case.Update, prog_node: std.Progress.Node) !void {
293 fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void {
297294 const arena = eval.arena;
298 const stdout = poller.reader(.stdout);
299 const stderr = poller.reader(.stderr);
300
301 poll: while (true) {
302 const Header = std.zig.Server.Message.Header;
303 while (stdout.buffered().len < @sizeOf(Header)) if (!try poller.poll()) break :poll;
304 const header = stdout.takeStruct(Header, .little) catch unreachable;
305 while (stdout.buffered().len < header.bytes_len) if (!try poller.poll()) break :poll;
306 const body = stdout.take(header.bytes_len) catch unreachable;
295 const stdout = mr.fileReader(0);
296 const stderr = &mr.fileReader(1).interface;
297 const Header = std.zig.Server.Message.Header;
298
299 while (true) {
300 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
301 error.EndOfStream => break,
302 error.ReadFailed => return stdout.err.?,
303 };
304 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
305 // If this panic triggers it might be helpful to rework this
306 // code to print the stderr from the abnormally terminated child.
307 error.EndOfStream => @panic("unexpected mid-message end of stream"),
308 error.ReadFailed => return stdout.err.?,
309 };
307310
308311 switch (header.tag) {
309312 .error_bundle => {
310313 const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
311314 if (stderr.bufferedLen() > 0) {
312 const stderr_data = try poller.toOwnedSlice(.stderr);
315 const stderr_data = try mr.toOwnedSlice(1);
313316 if (eval.allow_stderr) {
314317 std.log.info("error_bundle stderr:\n{s}", .{stderr_data});
315318 } else {
......@@ -326,7 +329,7 @@ const Eval = struct {
326329 var r: std.Io.Reader = .fixed(body);
327330 _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
328331 if (stderr.bufferedLen() > 0) {
329 const stderr_data = try poller.toOwnedSlice(.stderr);
332 const stderr_data = try mr.toOwnedSlice(1);
330333 if (eval.allow_stderr) {
331334 std.log.info("emit_digest stderr:\n{s}", .{stderr_data});
332335 } else {
......@@ -358,11 +361,12 @@ const Eval = struct {
358361 }
359362 }
360363
361 if (stderr.bufferedLen() > 0) {
364 const buffered_stderr = stderr.buffered();
365 if (buffered_stderr.len > 0) {
362366 if (eval.allow_stderr) {
363 std.log.info("stderr:\n{s}", .{stderr.buffered()});
367 std.log.info("stderr:\n{s}", .{buffered_stderr});
364368 } else {
365 eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()});
369 eval.fatal("unexpected stderr:\n{s}", .{buffered_stderr});
366370 }
367371 }
368372
......@@ -588,23 +592,27 @@ const Eval = struct {
588592 };
589593 }
590594
591 fn end(eval: *Eval, poller: *Poller) !void {
595 fn end(eval: *Eval, mr: *Io.File.MultiReader) !void {
592596 requestExit(eval.child, eval);
593597
594 const stdout = poller.reader(.stdout);
595 const stderr = poller.reader(.stderr);
598 const stdout = mr.fileReader(0);
599 const Header = std.zig.Server.Message.Header;
596600
597 poll: while (true) {
598 const Header = std.zig.Server.Message.Header;
599 while (stdout.buffered().len < @sizeOf(Header)) if (!try poller.poll()) break :poll;
600 const header = stdout.takeStruct(Header, .little) catch unreachable;
601 while (stdout.buffered().len < header.bytes_len) if (!try poller.poll()) break :poll;
602 stdout.toss(header.bytes_len);
601 while (true) {
602 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
603 error.EndOfStream => break,
604 error.ReadFailed => return stdout.err.?,
605 };
606 stdout.interface.discardAll(header.bytes_len) catch |err| switch (err) {
607 error.ReadFailed => return stdout.err.?,
608 error.EndOfStream => |e| return e,
609 };
603610 }
604611
605 if (stderr.bufferedLen() > 0) {
606 eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()});
607 }
612 try mr.fillRemaining(.none);
613
614 const stderr = mr.reader(1).buffered();
615 if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr});
608616 }
609617
610618 fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void {