authorgravatar for sahnvour@pm.meSahnvour <sahnvour@pm.me> 2023-08-11 12:19:56+02:00
committergravatar for sahnvour@pm.meSahnvour <sahnvour@pm.me> 2023-08-13 10:56:28+02:00
log078e3305555f117efbaa83a91b2e79444847363c
tree0149ebe23cd28dcbfb5f6ec4d3fe1b65e47467e9
parent0461a64a93f0596e98b62d596bb547e5455577d2

std.Build: make number of collected stack frames configurable


2 files changed, 70 insertions(+), 42 deletions(-)

lib/std/Build.zig+40-20
......@@ -102,6 +102,10 @@ args: ?[][]const u8 = null,
102102debug_log_scopes: []const []const u8 = &.{},
103103debug_compile_errors: bool = false,
104104debug_pkg_config: bool = false,
105/// Number of stack frames captured when a `StackTrace` is recorded for debug purposes,
106/// in particular at `Step` creation.
107/// Set to 0 to disable stack collection.
108debug_stack_frames_count: u8 = 8,
105109
106110/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
107111enable_darling: bool = false,
......@@ -1764,33 +1768,49 @@ pub fn dumpBadGetPathHelp(
17641768 });
17651769
17661770 const tty_config = std.io.tty.detectConfig(stderr);
1767 tty_config.setColor(w, .red) catch {};
1768 try stderr.writeAll(" The step was created by this stack trace:\n");
1769 tty_config.setColor(w, .reset) catch {};
1770
1771 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
1772 try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
1773 return;
1774 };
1775 const ally = debug_info.allocator;
1776 std.debug.writeStackTrace(s.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
1777 try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
1778 return;
1779 };
1780 if (asking_step) |as| {
1771 if (s.getStackTrace()) |stack_trace| {
17811772 tty_config.setColor(w, .red) catch {};
1782 try stderr.writeAll(" The step that is missing a dependency on the above step was created by this stack trace:\n");
1773 try stderr.writeAll(" The step was created by this stack trace:\n");
17831774 tty_config.setColor(w, .reset) catch {};
17841775
1785 std.debug.writeStackTrace(as.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
1776 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
1777 try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
1778 return;
1779 };
1780 const ally = debug_info.allocator;
1781
1782 std.debug.writeStackTrace(stack_trace, w, ally, debug_info, tty_config) catch |err| {
17861783 try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
17871784 return;
17881785 };
1786 if (asking_step) |as| {
1787 tty_config.setColor(w, .red) catch {};
1788 try stderr.writer().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
1789 tty_config.setColor(w, .reset) catch {};
1790
1791 if (as.getStackTrace()) |as_stack_trace| {
1792 std.debug.writeStackTrace(as_stack_trace, w, ally, debug_info, tty_config) catch |err| {
1793 try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
1794 return;
1795 };
1796 } else {
1797 const field = "debug_stack_frames_count";
1798 comptime assert(@hasField(Build, field));
1799 tty_config.setColor(w, .yellow) catch {};
1800 try stderr.writer().print("no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{});
1801 tty_config.setColor(w, .reset) catch {};
1802 }
1803 }
1804 tty_config.setColor(w, .red) catch {};
1805 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");
1806 tty_config.setColor(w, .reset) catch {};
1807 } else {
1808 const field = "debug_stack_frames_count";
1809 comptime assert(@hasField(Build, field));
1810 tty_config.setColor(w, .yellow) catch {};
1811 try stderr.writer().print("no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{});
1812 tty_config.setColor(w, .reset) catch {};
17891813 }
1790
1791 tty_config.setColor(w, .red) catch {};
1792 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");
1793 tty_config.setColor(w, .reset) catch {};
17941814}
17951815
17961816/// Allocates a new string for assigning a value to a named macro.
lib/std/Build/Step.zig+30-22
......@@ -39,7 +39,7 @@ test_results: TestResults,
3939
4040/// The return address associated with creation of this step that can be useful
4141/// to print along with debugging messages.
42debug_stack_trace: [n_debug_stack_frames]usize,
42debug_stack_trace: []usize,
4343
4444pub const TestResults = struct {
4545 fail_count: u32 = 0,
......@@ -58,8 +58,6 @@ pub const TestResults = struct {
5858
5959pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void;
6060
61const n_debug_stack_frames = 4;
62
6361pub const State = enum {
6462 precheck_unstarted,
6563 precheck_started,
......@@ -140,14 +138,6 @@ pub const StepOptions = struct {
140138pub fn init(options: StepOptions) Step {
141139 const arena = options.owner.allocator;
142140
143 var addresses = [1]usize{0} ** n_debug_stack_frames;
144 const first_ret_addr = options.first_ret_addr orelse @returnAddress();
145 var stack_trace = std.builtin.StackTrace{
146 .instruction_addresses = &addresses,
147 .index = 0,
148 };
149 std.debug.captureStackTrace(first_ret_addr, &stack_trace);
150
151141 return .{
152142 .id = options.id,
153143 .name = arena.dupe(u8, options.name) catch @panic("OOM"),
......@@ -157,7 +147,17 @@ pub fn init(options: StepOptions) Step {
157147 .dependants = .{},
158148 .state = .precheck_unstarted,
159149 .max_rss = options.max_rss,
160 .debug_stack_trace = addresses,
150 .debug_stack_trace = blk: {
151 const addresses = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM");
152 @memset(addresses, 0);
153 const first_ret_addr = options.first_ret_addr orelse @returnAddress();
154 var stack_trace = std.builtin.StackTrace{
155 .instruction_addresses = addresses,
156 .index = 0,
157 };
158 std.debug.captureStackTrace(first_ret_addr, &stack_trace);
159 break :blk addresses;
160 },
161161 .result_error_msgs = .{},
162162 .result_error_bundle = std.zig.ErrorBundle.empty,
163163 .result_cached = false,
......@@ -199,14 +199,14 @@ pub fn dependOn(self: *Step, other: *Step) void {
199199 self.dependencies.append(other) catch @panic("OOM");
200200}
201201
202pub fn getStackTrace(s: *Step) std.builtin.StackTrace {
203 const stack_addresses = &s.debug_stack_trace;
202pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace {
204203 var len: usize = 0;
205 while (len < n_debug_stack_frames and stack_addresses[len] != 0) {
204 while (len < s.debug_stack_trace.len and s.debug_stack_trace[len] != 0) {
206205 len += 1;
207206 }
208 return .{
209 .instruction_addresses = stack_addresses,
207
208 return if (len == 0) null else .{
209 .instruction_addresses = s.debug_stack_trace,
210210 .index = len,
211211 };
212212}
......@@ -245,11 +245,19 @@ pub fn dump(step: *Step) void {
245245 return;
246246 };
247247 const ally = debug_info.allocator;
248 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
249 std.debug.writeStackTrace(step.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
250 stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
251 return;
252 };
248 if (step.getStackTrace()) |stack_trace| {
249 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
250 std.debug.writeStackTrace(stack_trace, w, ally, debug_info, tty_config) catch |err| {
251 stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
252 return;
253 };
254 } else {
255 const field = "debug_stack_frames_count";
256 comptime assert(@hasField(Build, field));
257 tty_config.setColor(w, .yellow) catch {};
258 w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
259 tty_config.setColor(w, .reset) catch {};
260 }
253261}
254262
255263const Step = @This();