authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-14 22:17:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-14 22:17:29-07:00
log987f63208e4bdd044768465f1581d03ee8964e28
tree41715b4188d654a96ccdc1e217eef7e088dafef7
parentf6c1b71c220406d60ca4bdf9c949e775f7fca466

build runner: handle compiler subprocess failures gracefully

Compilation errors now report a failure on rebuilds triggered by file system watches. Compiler crashes now report failure correctly on rebuilds triggered by file system watches. The compiler subprocess is restarted if a broken pipe is encountered on a rebuild.

1 files changed, 44 insertions(+), 3 deletions(-)

lib/std/Build/Step.zig+44-3
......@@ -374,10 +374,37 @@ pub fn evalZigProcess(
374374 prog_node: std.Progress.Node,
375375 watch: bool,
376376) !?[]const u8 {
377 if (s.getZigProcess()) |zp| {
377 if (s.getZigProcess()) |zp| update: {
378378 assert(watch);
379379 if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd);
380 return zigProcessUpdate(s, zp, watch);
380 const result = zigProcessUpdate(s, zp, watch) catch |err| switch (err) {
381 error.BrokenPipe => {
382 // Process restart required.
383 const term = zp.child.wait() catch |e| {
384 return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(e) });
385 };
386 _ = term;
387 s.clearZigProcess();
388 break :update;
389 },
390 else => |e| return e,
391 };
392
393 if (s.result_error_bundle.errorMessageCount() > 0)
394 return s.fail("{d} compilation errors", .{s.result_error_bundle.errorMessageCount()});
395
396 if (s.result_error_msgs.items.len > 0 and result == null) {
397 // Crash detected.
398 const term = zp.child.wait() catch |e| {
399 return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(e) });
400 };
401 s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0;
402 s.clearZigProcess();
403 try handleChildProcessTerm(s, term, null, argv);
404 return error.MakeFailed;
405 }
406
407 return result;
381408 }
382409 assert(argv.len != 0);
383410 const b = s.owner;
......@@ -399,7 +426,7 @@ pub fn evalZigProcess(
399426 argv[0], @errorName(err),
400427 });
401428
402 const zp = try arena.create(ZigProcess);
429 const zp = try gpa.create(ZigProcess);
403430 zp.* = .{
404431 .child = child,
405432 .poller = std.io.poll(gpa, ZigProcess.StreamEnum, .{
......@@ -590,6 +617,20 @@ fn setZigProcess(s: *Step, zp: *ZigProcess) void {
590617 }
591618}
592619
620fn clearZigProcess(s: *Step) void {
621 const gpa = s.owner.allocator;
622 switch (s.id) {
623 .compile => {
624 const compile = s.cast(Compile).?;
625 if (compile.zig_process) |zp| {
626 gpa.destroy(zp);
627 compile.zig_process = null;
628 }
629 },
630 else => unreachable,
631 }
632}
633
593634fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
594635 const header: std.zig.Client.Message.Header = .{
595636 .tag = tag,