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(...@@ -374,10 +374,37 @@ pub fn evalZigProcess(
374 prog_node: std.Progress.Node,374 prog_node: std.Progress.Node,
375 watch: bool,375 watch: bool,
376) !?[]const u8 {376) !?[]const u8 {
377 if (s.getZigProcess()) |zp| {377 if (s.getZigProcess()) |zp| update: {
378 assert(watch);378 assert(watch);
379 if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd);379 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;
381 }408 }
382 assert(argv.len != 0);409 assert(argv.len != 0);
383 const b = s.owner;410 const b = s.owner;
...@@ -399,7 +426,7 @@ pub fn evalZigProcess(...@@ -399,7 +426,7 @@ pub fn evalZigProcess(
399 argv[0], @errorName(err),426 argv[0], @errorName(err),
400 });427 });
401428
402 const zp = try arena.create(ZigProcess);429 const zp = try gpa.create(ZigProcess);
403 zp.* = .{430 zp.* = .{
404 .child = child,431 .child = child,
405 .poller = std.io.poll(gpa, ZigProcess.StreamEnum, .{432 .poller = std.io.poll(gpa, ZigProcess.StreamEnum, .{
...@@ -590,6 +617,20 @@ fn setZigProcess(s: *Step, zp: *ZigProcess) void {...@@ -590,6 +617,20 @@ fn setZigProcess(s: *Step, zp: *ZigProcess) void {
590 }617 }
591}618}
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
593fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {634fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
594 const header: std.zig.Client.Message.Header = .{635 const header: std.zig.Client.Message.Header = .{
595 .tag = tag,636 .tag = tag,