authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-13 13:54:51-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-08-13 13:54:51-07:00
loga1049d4561b9c34dc8787dd09e4de25afee5965b
tree290d56b1c362e50f14db98e703c6fcb4fd2173ad
parent2ceeade99a40c4c15798bc2878ae3318c5a3710f
parentf43402f883bff6c1934c551b5cb29f70dac1b1b6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16773 from Sahnvour/build-stack-frames

std.Build: make number of collected stack frames configurable

2 files changed, 40 insertions(+), 44 deletions(-)

lib/std/Build.zig+7-15
...@@ -102,6 +102,10 @@ args: ?[][]const u8 = null,...@@ -102,6 +102,10 @@ args: ?[][]const u8 = null,
102debug_log_scopes: []const []const u8 = &.{},102debug_log_scopes: []const []const u8 = &.{},
103debug_compile_errors: bool = false,103debug_compile_errors: bool = false,
104debug_pkg_config: bool = false,104debug_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
106/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.110/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
107enable_darling: bool = false,111enable_darling: bool = false,
...@@ -1953,26 +1957,14 @@ pub fn dumpBadGetPathHelp(...@@ -1953,26 +1957,14 @@ pub fn dumpBadGetPathHelp(
1953 try stderr.writeAll(" The step was created by this stack trace:\n");1957 try stderr.writeAll(" The step was created by this stack trace:\n");
1954 tty_config.setColor(w, .reset) catch {};1958 tty_config.setColor(w, .reset) catch {};
19551959
1956 const debug_info = std.debug.getSelfDebugInfo() catch |err| {1960 s.dump(stderr);
1957 try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
1958 return;
1959 };
1960 const ally = debug_info.allocator;
1961 std.debug.writeStackTrace(s.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
1962 try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
1963 return;
1964 };
1965 if (asking_step) |as| {1961 if (asking_step) |as| {
1966 tty_config.setColor(w, .red) catch {};1962 tty_config.setColor(w, .red) catch {};
1967 try stderr.writeAll(" The step that is missing a dependency on the above step was created by this stack trace:\n");1963 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});
1968 tty_config.setColor(w, .reset) catch {};1964 tty_config.setColor(w, .reset) catch {};
19691965
1970 std.debug.writeStackTrace(as.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {1966 as.dump(stderr);
1971 try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
1972 return;
1973 };
1974 }1967 }
1975
1976 tty_config.setColor(w, .red) catch {};1968 tty_config.setColor(w, .red) catch {};
1977 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");1969 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");
1978 tty_config.setColor(w, .reset) catch {};1970 tty_config.setColor(w, .reset) catch {};
lib/std/Build/Step.zig+33-29
...@@ -39,7 +39,7 @@ test_results: TestResults,...@@ -39,7 +39,7 @@ test_results: TestResults,
3939
40/// The return address associated with creation of this step that can be useful40/// The return address associated with creation of this step that can be useful
41/// to print along with debugging messages.41/// to print along with debugging messages.
42debug_stack_trace: [n_debug_stack_frames]usize,42debug_stack_trace: []usize,
4343
44pub const TestResults = struct {44pub const TestResults = struct {
45 fail_count: u32 = 0,45 fail_count: u32 = 0,
...@@ -58,8 +58,6 @@ pub const TestResults = struct {...@@ -58,8 +58,6 @@ pub const TestResults = struct {
5858
59pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void;59pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void;
6060
61const n_debug_stack_frames = 4;
62
63pub const State = enum {61pub const State = enum {
64 precheck_unstarted,62 precheck_unstarted,
65 precheck_started,63 precheck_started,
...@@ -140,14 +138,6 @@ pub const StepOptions = struct {...@@ -140,14 +138,6 @@ pub const StepOptions = struct {
140pub fn init(options: StepOptions) Step {138pub fn init(options: StepOptions) Step {
141 const arena = options.owner.allocator;139 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
151 return .{141 return .{
152 .id = options.id,142 .id = options.id,
153 .name = arena.dupe(u8, options.name) catch @panic("OOM"),143 .name = arena.dupe(u8, options.name) catch @panic("OOM"),
...@@ -157,7 +147,17 @@ pub fn init(options: StepOptions) Step {...@@ -157,7 +147,17 @@ pub fn init(options: StepOptions) Step {
157 .dependants = .{},147 .dependants = .{},
158 .state = .precheck_unstarted,148 .state = .precheck_unstarted,
159 .max_rss = options.max_rss,149 .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 },
161 .result_error_msgs = .{},161 .result_error_msgs = .{},
162 .result_error_bundle = std.zig.ErrorBundle.empty,162 .result_error_bundle = std.zig.ErrorBundle.empty,
163 .result_cached = false,163 .result_cached = false,
...@@ -199,14 +199,14 @@ pub fn dependOn(self: *Step, other: *Step) void {...@@ -199,14 +199,14 @@ pub fn dependOn(self: *Step, other: *Step) void {
199 self.dependencies.append(other) catch @panic("OOM");199 self.dependencies.append(other) catch @panic("OOM");
200}200}
201201
202pub fn getStackTrace(s: *Step) std.builtin.StackTrace {202pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace {
203 const stack_addresses = &s.debug_stack_trace;
204 var len: usize = 0;203 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) {
206 len += 1;205 len += 1;
207 }206 }
208 return .{207
209 .instruction_addresses = stack_addresses,208 return if (len == 0) null else .{
209 .instruction_addresses = s.debug_stack_trace,
210 .index = len,210 .index = len,
211 };211 };
212}212}
...@@ -231,13 +231,9 @@ pub fn cast(step: *Step, comptime T: type) ?*T {...@@ -231,13 +231,9 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
231}231}
232232
233/// For debugging purposes, prints identifying information about this Step.233/// For debugging purposes, prints identifying information about this Step.
234pub fn dump(step: *Step) void {234pub fn dump(step: *Step, file: std.fs.File) void {
235 std.debug.getStderrMutex().lock();235 const w = file.writer();
236 defer std.debug.getStderrMutex().unlock();236 const tty_config = std.io.tty.detectConfig(file);
237
238 const stderr = std.io.getStdErr();
239 const w = stderr.writer();
240 const tty_config = std.io.tty.detectConfig(stderr);
241 const debug_info = std.debug.getSelfDebugInfo() catch |err| {237 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
242 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{238 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
243 @errorName(err),239 @errorName(err),
...@@ -245,11 +241,19 @@ pub fn dump(step: *Step) void {...@@ -245,11 +241,19 @@ pub fn dump(step: *Step) void {
245 return;241 return;
246 };242 };
247 const ally = debug_info.allocator;243 const ally = debug_info.allocator;
248 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};244 if (step.getStackTrace()) |stack_trace| {
249 std.debug.writeStackTrace(step.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {245 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
250 stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};246 std.debug.writeStackTrace(stack_trace, w, ally, debug_info, tty_config) catch |err| {
251 return;247 w.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
252 };248 return;
249 };
250 } else {
251 const field = "debug_stack_frames_count";
252 comptime assert(@hasField(Build, field));
253 tty_config.setColor(w, .yellow) catch {};
254 w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
255 tty_config.setColor(w, .reset) catch {};
256 }
253}257}
254258
255const Step = @This();259const Step = @This();