From 3185ff0b9fc6bd7cf4e68af972ab06a9627c6462 Mon Sep 17 00:00:00 2001 From: Parzival-3141 <29632054+Parzival-3141@users.noreply.github.com> Date: Tue, 2 May 2023 02:01:05 -0400 Subject: [PATCH 1/4] show errorReturnTrace when Step.makeFn errors --- lib/std/Build/Step.zig | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 15dbd7faed..42ddbcc01b 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -232,7 +232,19 @@ pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!voi error.MakeFailed => return error.MakeFailed, error.MakeSkipped => return error.MakeSkipped, else => { - s.result_error_msgs.append(arena, @errorName(err)) catch @panic("OOM"); + var msg_buffer = arena.alloc(u8, 4096) catch @panic("OOM"); + var stream = std.io.fixedBufferStream(msg_buffer); + const writer = stream.writer(); + + writer.writeAll("step failed with error ") catch @panic("msg_buffer OOM"); + writer.writeAll(@errorName(err)) catch @panic("msg_buffer OOM"); + + if (@errorReturnTrace()) |trace| { + writer.writeAll(":") catch @panic("msg_buffer OOM"); + trace.format("", .{}, writer) catch @panic("msg_buffer OOM"); + } + + s.result_error_msgs.append(arena, msg_buffer[0..stream.pos]) catch @panic("OOM"); return error.MakeFailed; }, }; From 0c5b9cb0c071530ca0d278628ae6e98b8b14ef38 Mon Sep 17 00:00:00 2001 From: Parzival-3141 <29632054+Parzival-3141@users.noreply.github.com> Date: Tue, 2 May 2023 04:23:43 -0400 Subject: [PATCH 2/4] print message instead of panicking on buffer overrun --- lib/std/Build/Step.zig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 42ddbcc01b..e45eb854da 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -236,14 +236,20 @@ pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!voi var stream = std.io.fixedBufferStream(msg_buffer); const writer = stream.writer(); - writer.writeAll("step failed with error ") catch @panic("msg_buffer OOM"); + writer.writeAll("step failed with error ") catch unreachable; writer.writeAll(@errorName(err)) catch @panic("msg_buffer OOM"); if (@errorReturnTrace()) |trace| { writer.writeAll(":") catch @panic("msg_buffer OOM"); - trace.format("", .{}, writer) catch @panic("msg_buffer OOM"); + trace.format("", .{}, writer) catch { + // Assumes trace.format has written everything up until failure + const overrun_msg = ".... errorReturnTrace exceeds buffer size!"; + for (msg_buffer[stream.pos - overrun_msg.len .. stream.pos], 0..) |*value, i| { + value.* = overrun_msg[i]; + } + }; } - + _ = arena.resize(msg_buffer, stream.pos); s.result_error_msgs.append(arena, msg_buffer[0..stream.pos]) catch @panic("OOM"); return error.MakeFailed; }, From a49d1827fe747267a07d6aefe01a3751c2f87ba6 Mon Sep 17 00:00:00 2001 From: Parzival-3141 <29632054+Parzival-3141@users.noreply.github.com> Date: Mon, 26 Aug 2024 21:08:37 -0400 Subject: [PATCH 3/4] store error trace and defer printing --- lib/compiler/build_runner.zig | 4 ++++ lib/std/Build/Step.zig | 37 ++++++++++++----------------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 690c937545..c840354acd 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -1216,6 +1216,10 @@ pub fn printErrorMessages( try stderr.writeAll(msg); try stderr.writeAll("\n"); } + + if (failing_step.result_error_trace) |trace| { + try trace.format("", .{}, stderr.writer()); + } } fn steps(builder: *std.Build, out_stream: anytype) !void { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index e45eb854da..cbb548dd37 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -41,6 +41,7 @@ max_rss: usize, result_error_msgs: std.ArrayListUnmanaged([]const u8), result_error_bundle: std.zig.ErrorBundle, +result_error_trace: ?*std.builtin.StackTrace, result_stderr: []const u8, result_cached: bool, result_duration_ns: ?u64, @@ -214,6 +215,7 @@ pub fn init(options: StepOptions) Step { }, .result_error_msgs = .{}, .result_error_bundle = std.zig.ErrorBundle.empty, + .result_error_trace = null, .result_stderr = "", .result_cached = false, .result_duration_ns = null, @@ -228,31 +230,16 @@ pub fn init(options: StepOptions) Step { pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!void { const arena = s.owner.allocator; - s.makeFn(s, options) catch |err| switch (err) { - error.MakeFailed => return error.MakeFailed, - error.MakeSkipped => return error.MakeSkipped, - else => { - var msg_buffer = arena.alloc(u8, 4096) catch @panic("OOM"); - var stream = std.io.fixedBufferStream(msg_buffer); - const writer = stream.writer(); - - writer.writeAll("step failed with error ") catch unreachable; - writer.writeAll(@errorName(err)) catch @panic("msg_buffer OOM"); - - if (@errorReturnTrace()) |trace| { - writer.writeAll(":") catch @panic("msg_buffer OOM"); - trace.format("", .{}, writer) catch { - // Assumes trace.format has written everything up until failure - const overrun_msg = ".... errorReturnTrace exceeds buffer size!"; - for (msg_buffer[stream.pos - overrun_msg.len .. stream.pos], 0..) |*value, i| { - value.* = overrun_msg[i]; - } - }; - } - _ = arena.resize(msg_buffer, stream.pos); - s.result_error_msgs.append(arena, msg_buffer[0..stream.pos]) catch @panic("OOM"); - return error.MakeFailed; - }, + s.makeFn(s, options) catch |err| { + switch (err) { + error.MakeFailed => return error.MakeFailed, + error.MakeSkipped => return error.MakeSkipped, + else => { + s.result_error_trace = @errorReturnTrace(); + s.addError("this step's make function failed with error {s}:", .{@errorName(err)}) catch @panic("OOM"); + return error.MakeFailed; + }, + } }; if (!s.test_results.isSuccess()) { From eb74a9d63d484a10f0e62c64de589260060856a5 Mon Sep 17 00:00:00 2001 From: Parzival-3141 <29632054+Parzival-3141@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:44:55 -0400 Subject: [PATCH 4/4] group error and trace for reporting in build runner Unlike the previous commit, this ensures that the error message and trace are printed together. --- lib/compiler/build_runner.zig | 12 ++++++++---- lib/std/Build/Step.zig | 19 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index c840354acd..a4e5a4971b 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -893,7 +893,7 @@ fn printStepFailure( try ttyconf.setColor(stderr, .reset); } try stderr.writeAll("\n"); - } else if (s.result_error_msgs.items.len > 0) { + } else if (s.result_error_msgs.items.len > 0 or s.make_error_trace != null) { try ttyconf.setColor(stderr, .red); try stderr.writeAll(" failure\n"); try ttyconf.setColor(stderr, .reset); @@ -1102,7 +1102,7 @@ fn workerMakeOneStep( // No matter the result, we want to display error/warning messages. const show_compile_errors = !run.prominent_compile_errors and s.result_error_bundle.errorMessageCount() > 0; - const show_error_msgs = s.result_error_msgs.items.len > 0; + const show_error_msgs = s.result_error_msgs.items.len > 0 or s.make_error_trace != null; const show_stderr = s.result_stderr.len > 0; if (show_error_msgs or show_compile_errors or show_stderr) { @@ -1217,8 +1217,12 @@ pub fn printErrorMessages( try stderr.writeAll("\n"); } - if (failing_step.result_error_trace) |trace| { - try trace.format("", .{}, stderr.writer()); + if (failing_step.make_error_trace) |make_err| { + try ttyconf.setColor(stderr, .red); + try stderr.writeAll("error: "); + try ttyconf.setColor(stderr, .reset); + try stderr.writer().print("this step's make function failed with error {s}", .{@errorName(make_err.err)}); + if (make_err.trace) |trace| try trace.format("", .{}, stderr.writer()); } } diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index cbb548dd37..714e97245f 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -41,7 +41,8 @@ max_rss: usize, result_error_msgs: std.ArrayListUnmanaged([]const u8), result_error_bundle: std.zig.ErrorBundle, -result_error_trace: ?*std.builtin.StackTrace, +make_error_trace: ?MakeErrorTrace, + result_stderr: []const u8, result_cached: bool, result_duration_ns: ?u64, @@ -53,6 +54,12 @@ test_results: TestResults, /// to print along with debugging messages. debug_stack_trace: []usize, +/// Storage for unhandled errors returned by the make function. +pub const MakeErrorTrace = struct { + err: anyerror, + trace: ?*std.builtin.StackTrace, +}; + pub const TestResults = struct { fail_count: u32 = 0, skip_count: u32 = 0, @@ -215,7 +222,7 @@ pub fn init(options: StepOptions) Step { }, .result_error_msgs = .{}, .result_error_bundle = std.zig.ErrorBundle.empty, - .result_error_trace = null, + .make_error_trace = null, .result_stderr = "", .result_cached = false, .result_duration_ns = null, @@ -225,8 +232,8 @@ pub fn init(options: StepOptions) Step { } /// If the Step's `make` function reports `error.MakeFailed`, it indicates they -/// have already reported the error. Otherwise, we add a simple error report -/// here. +/// have already reported the error. Otherwise, we store the error for reporting +/// later. pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!void { const arena = s.owner.allocator; @@ -235,8 +242,7 @@ pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!voi error.MakeFailed => return error.MakeFailed, error.MakeSkipped => return error.MakeSkipped, else => { - s.result_error_trace = @errorReturnTrace(); - s.addError("this step's make function failed with error {s}:", .{@errorName(err)}) catch @panic("OOM"); + s.make_error_trace = .{ .err = err, .trace = @errorReturnTrace() }; return error.MakeFailed; }, } @@ -900,6 +906,7 @@ fn reset(step: *Step, gpa: Allocator) void { step.result_error_bundle.deinit(gpa); step.result_error_bundle = std.zig.ErrorBundle.empty; + step.make_error_trace = null; } /// Implementation detail of file watching. Prepares the step for being re-evaluated.