| ... | ... | @@ -28,6 +28,7 @@ fn logImpl( |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 30 | pub fn main(init: std.process.Init) !void { |
| 31 | const gpa = init.gpa; |
| 31 | 32 | const fatal = std.process.fatal; |
| 32 | 33 | const arena = init.arena.allocator(); |
| 33 | 34 | const io = init.io; |
| ... | ... | @@ -224,11 +225,10 @@ pub fn main(init: std.process.Init) !void { |
| 224 | 225 | .enable_darling = enable_darling, |
| 225 | 226 | }; |
| 226 | 227 | |
| 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(); |
| 232 | 232 | |
| 233 | 233 | for (case.updates) |update| { |
| 234 | 234 | var update_node = target_prog_node.start(update.name, 0); |
| ... | ... | @@ -243,10 +243,10 @@ pub fn main(init: std.process.Init) !void { |
| 243 | 243 | |
| 244 | 244 | eval.write(update); |
| 245 | 245 | try eval.requestUpdate(); |
| 246 | | try eval.check(&poller, update, update_node); |
| 246 | try eval.check(&multi_reader, update, update_node); |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | | try eval.end(&poller); |
| 249 | try eval.end(&multi_reader); |
| 250 | 250 | |
| 251 | 251 | waitChild(&child, &eval); |
| 252 | 252 | } |
| ... | ... | @@ -272,9 +272,6 @@ const Eval = struct { |
| 272 | 272 | enable_wasmtime: bool, |
| 273 | 273 | enable_darling: bool, |
| 274 | 274 | |
| 275 | | const StreamEnum = enum { stdout, stderr }; |
| 276 | | const Poller = Io.Poller(StreamEnum); |
| 277 | | |
| 278 | 275 | /// Currently this function assumes the previous updates have already been written. |
| 279 | 276 | fn write(eval: *Eval, update: Case.Update) void { |
| 280 | 277 | const io = eval.io; |
| ... | ... | @@ -293,23 +290,29 @@ const Eval = struct { |
| 293 | 290 | } |
| 294 | 291 | } |
| 295 | 292 | |
| 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 | 294 | 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 | }; |
| 307 | 310 | |
| 308 | 311 | switch (header.tag) { |
| 309 | 312 | .error_bundle => { |
| 310 | 313 | const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); |
| 311 | 314 | if (stderr.bufferedLen() > 0) { |
| 312 | | const stderr_data = try poller.toOwnedSlice(.stderr); |
| 315 | const stderr_data = try mr.toOwnedSlice(1); |
| 313 | 316 | if (eval.allow_stderr) { |
| 314 | 317 | std.log.info("error_bundle stderr:\n{s}", .{stderr_data}); |
| 315 | 318 | } else { |
| ... | ... | @@ -326,7 +329,7 @@ const Eval = struct { |
| 326 | 329 | var r: std.Io.Reader = .fixed(body); |
| 327 | 330 | _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; |
| 328 | 331 | if (stderr.bufferedLen() > 0) { |
| 329 | | const stderr_data = try poller.toOwnedSlice(.stderr); |
| 332 | const stderr_data = try mr.toOwnedSlice(1); |
| 330 | 333 | if (eval.allow_stderr) { |
| 331 | 334 | std.log.info("emit_digest stderr:\n{s}", .{stderr_data}); |
| 332 | 335 | } else { |
| ... | ... | @@ -358,11 +361,12 @@ const Eval = struct { |
| 358 | 361 | } |
| 359 | 362 | } |
| 360 | 363 | |
| 361 | | if (stderr.bufferedLen() > 0) { |
| 364 | const buffered_stderr = stderr.buffered(); |
| 365 | if (buffered_stderr.len > 0) { |
| 362 | 366 | if (eval.allow_stderr) { |
| 363 | | std.log.info("stderr:\n{s}", .{stderr.buffered()}); |
| 367 | std.log.info("stderr:\n{s}", .{buffered_stderr}); |
| 364 | 368 | } else { |
| 365 | | eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()}); |
| 369 | eval.fatal("unexpected stderr:\n{s}", .{buffered_stderr}); |
| 366 | 370 | } |
| 367 | 371 | } |
| 368 | 372 | |
| ... | ... | @@ -588,23 +592,27 @@ const Eval = struct { |
| 588 | 592 | }; |
| 589 | 593 | } |
| 590 | 594 | |
| 591 | | fn end(eval: *Eval, poller: *Poller) !void { |
| 595 | fn end(eval: *Eval, mr: *Io.File.MultiReader) !void { |
| 592 | 596 | requestExit(eval.child, eval); |
| 593 | 597 | |
| 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; |
| 596 | 600 | |
| 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 | }; |
| 603 | 610 | } |
| 604 | 611 | |
| 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}); |
| 608 | 616 | } |
| 609 | 617 | |
| 610 | 618 | fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void { |