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 12:10:01-08:00
logccf85b51ea21fc88cfa00aa279704074301cd38c
tree65051bc81390a0058235c765aba697a172f5e029
parenta04e296d8840867cf792ae701a0513b99c6d4411

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(...@@ -28,6 +28,7 @@ fn logImpl(
28}28}
2929
30pub fn main(init: std.process.Init) !void {30pub fn main(init: std.process.Init) !void {
31 const gpa = init.gpa;
31 const fatal = std.process.fatal;32 const fatal = std.process.fatal;
32 const arena = init.arena.allocator();33 const arena = init.arena.allocator();
33 const io = init.io;34 const io = init.io;
...@@ -224,11 +225,10 @@ pub fn main(init: std.process.Init) !void {...@@ -224,11 +225,10 @@ pub fn main(init: std.process.Init) !void {
224 .enable_darling = enable_darling,225 .enable_darling = enable_darling,
225 };226 };
226227
227 var poller = Io.poll(arena, Eval.StreamEnum, .{228 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;
228 .stdout = child.stdout.?,229 var multi_reader: Io.File.MultiReader = undefined;
229 .stderr = child.stderr.?,230 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
230 });231 defer multi_reader.deinit();
231 defer poller.deinit();
232232
233 for (case.updates) |update| {233 for (case.updates) |update| {
234 var update_node = target_prog_node.start(update.name, 0);234 var update_node = target_prog_node.start(update.name, 0);
...@@ -243,10 +243,10 @@ pub fn main(init: std.process.Init) !void {...@@ -243,10 +243,10 @@ pub fn main(init: std.process.Init) !void {
243243
244 eval.write(update);244 eval.write(update);
245 try eval.requestUpdate();245 try eval.requestUpdate();
246 try eval.check(&poller, update, update_node);246 try eval.check(&multi_reader, update, update_node);
247 }247 }
248248
249 try eval.end(&poller);249 try eval.end(&multi_reader);
250250
251 waitChild(&child, &eval);251 waitChild(&child, &eval);
252 }252 }
...@@ -272,9 +272,6 @@ const Eval = struct {...@@ -272,9 +272,6 @@ const Eval = struct {
272 enable_wasmtime: bool,272 enable_wasmtime: bool,
273 enable_darling: bool,273 enable_darling: bool,
274274
275 const StreamEnum = enum { stdout, stderr };
276 const Poller = Io.Poller(StreamEnum);
277
278 /// Currently this function assumes the previous updates have already been written.275 /// Currently this function assumes the previous updates have already been written.
279 fn write(eval: *Eval, update: Case.Update) void {276 fn write(eval: *Eval, update: Case.Update) void {
280 const io = eval.io;277 const io = eval.io;
...@@ -293,23 +290,29 @@ const Eval = struct {...@@ -293,23 +290,29 @@ const Eval = struct {
293 }290 }
294 }291 }
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 {
297 const arena = eval.arena;294 const arena = eval.arena;
298 const stdout = poller.reader(.stdout);295 const stdout = mr.fileReader(0);
299 const stderr = poller.reader(.stderr);296 const stderr = &mr.fileReader(1).interface;
300297 const Header = std.zig.Server.Message.Header;
301 poll: while (true) {298
302 const Header = std.zig.Server.Message.Header;299 while (true) {
303 while (stdout.buffered().len < @sizeOf(Header)) if (!try poller.poll()) break :poll;300 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
304 const header = stdout.takeStruct(Header, .little) catch unreachable;301 error.EndOfStream => break,
305 while (stdout.buffered().len < header.bytes_len) if (!try poller.poll()) break :poll;302 error.ReadFailed => return stdout.err.?,
306 const body = stdout.take(header.bytes_len) catch unreachable;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
308 switch (header.tag) {311 switch (header.tag) {
309 .error_bundle => {312 .error_bundle => {
310 const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);313 const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
311 if (stderr.bufferedLen() > 0) {314 if (stderr.bufferedLen() > 0) {
312 const stderr_data = try poller.toOwnedSlice(.stderr);315 const stderr_data = try mr.toOwnedSlice(1);
313 if (eval.allow_stderr) {316 if (eval.allow_stderr) {
314 std.log.info("error_bundle stderr:\n{s}", .{stderr_data});317 std.log.info("error_bundle stderr:\n{s}", .{stderr_data});
315 } else {318 } else {
...@@ -326,7 +329,7 @@ const Eval = struct {...@@ -326,7 +329,7 @@ const Eval = struct {
326 var r: std.Io.Reader = .fixed(body);329 var r: std.Io.Reader = .fixed(body);
327 _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;330 _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
328 if (stderr.bufferedLen() > 0) {331 if (stderr.bufferedLen() > 0) {
329 const stderr_data = try poller.toOwnedSlice(.stderr);332 const stderr_data = try mr.toOwnedSlice(1);
330 if (eval.allow_stderr) {333 if (eval.allow_stderr) {
331 std.log.info("emit_digest stderr:\n{s}", .{stderr_data});334 std.log.info("emit_digest stderr:\n{s}", .{stderr_data});
332 } else {335 } else {
...@@ -358,11 +361,12 @@ const Eval = struct {...@@ -358,11 +361,12 @@ const Eval = struct {
358 }361 }
359 }362 }
360363
361 if (stderr.bufferedLen() > 0) {364 const buffered_stderr = stderr.buffered();
365 if (buffered_stderr.len > 0) {
362 if (eval.allow_stderr) {366 if (eval.allow_stderr) {
363 std.log.info("stderr:\n{s}", .{stderr.buffered()});367 std.log.info("stderr:\n{s}", .{buffered_stderr});
364 } else {368 } else {
365 eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()});369 eval.fatal("unexpected stderr:\n{s}", .{buffered_stderr});
366 }370 }
367 }371 }
368372
...@@ -588,23 +592,27 @@ const Eval = struct {...@@ -588,23 +592,27 @@ const Eval = struct {
588 };592 };
589 }593 }
590594
591 fn end(eval: *Eval, poller: *Poller) !void {595 fn end(eval: *Eval, mr: *Io.File.MultiReader) !void {
592 requestExit(eval.child, eval);596 requestExit(eval.child, eval);
593597
594 const stdout = poller.reader(.stdout);598 const stdout = mr.fileReader(0);
595 const stderr = poller.reader(.stderr);599 const Header = std.zig.Server.Message.Header;
596600
597 poll: while (true) {601 while (true) {
598 const Header = std.zig.Server.Message.Header;602 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
599 while (stdout.buffered().len < @sizeOf(Header)) if (!try poller.poll()) break :poll;603 error.EndOfStream => break,
600 const header = stdout.takeStruct(Header, .little) catch unreachable;604 error.ReadFailed => return stdout.err.?,
601 while (stdout.buffered().len < header.bytes_len) if (!try poller.poll()) break :poll;605 };
602 stdout.toss(header.bytes_len);606 stdout.interface.discardAll(header.bytes_len) catch |err| switch (err) {
607 error.ReadFailed => return stdout.err.?,
608 error.EndOfStream => |e| return e,
609 };
603 }610 }
604611
605 if (stderr.bufferedLen() > 0) {612 try mr.fillRemaining(.none);
606 eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()});613
607 }614 const stderr = mr.reader(1).buffered();
615 if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr});
608 }616 }
609617
610 fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void {618 fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void {