Skip to content

Commit

Permalink
Merge pull request #16773 from Sahnvour/build-stack-frames
Browse files Browse the repository at this point in the history
std.Build: make number of collected stack frames configurable
  • Loading branch information
andrewrk authored Aug 13, 2023
2 parents 2ceeade + f43402f commit a1049d4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 44 deletions.
22 changes: 7 additions & 15 deletions lib/std/Build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ args: ?[][]const u8 = null,
debug_log_scopes: []const []const u8 = &.{},
debug_compile_errors: bool = false,
debug_pkg_config: bool = false,
/// Number of stack frames captured when a `StackTrace` is recorded for debug purposes,
/// in particular at `Step` creation.
/// Set to 0 to disable stack collection.
debug_stack_frames_count: u8 = 8,

/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
enable_darling: bool = false,
Expand Down Expand Up @@ -1953,26 +1957,14 @@ pub fn dumpBadGetPathHelp(
try stderr.writeAll(" The step was created by this stack trace:\n");
tty_config.setColor(w, .reset) catch {};

const debug_info = std.debug.getSelfDebugInfo() catch |err| {
try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
return;
};
const ally = debug_info.allocator;
std.debug.writeStackTrace(s.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
return;
};
s.dump(stderr);
if (asking_step) |as| {
tty_config.setColor(w, .red) catch {};
try stderr.writeAll(" The step that is missing a dependency on the above step was created by this stack trace:\n");
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});
tty_config.setColor(w, .reset) catch {};

std.debug.writeStackTrace(as.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
return;
};
as.dump(stderr);
}

tty_config.setColor(w, .red) catch {};
try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");
tty_config.setColor(w, .reset) catch {};
Expand Down
62 changes: 33 additions & 29 deletions lib/std/Build/Step.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ test_results: TestResults,

/// The return address associated with creation of this step that can be useful
/// to print along with debugging messages.
debug_stack_trace: [n_debug_stack_frames]usize,
debug_stack_trace: []usize,

pub const TestResults = struct {
fail_count: u32 = 0,
Expand All @@ -58,8 +58,6 @@ pub const TestResults = struct {

pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void;

const n_debug_stack_frames = 4;

pub const State = enum {
precheck_unstarted,
precheck_started,
Expand Down Expand Up @@ -140,14 +138,6 @@ pub const StepOptions = struct {
pub fn init(options: StepOptions) Step {
const arena = options.owner.allocator;

var addresses = [1]usize{0} ** n_debug_stack_frames;
const first_ret_addr = options.first_ret_addr orelse @returnAddress();
var stack_trace = std.builtin.StackTrace{
.instruction_addresses = &addresses,
.index = 0,
};
std.debug.captureStackTrace(first_ret_addr, &stack_trace);

return .{
.id = options.id,
.name = arena.dupe(u8, options.name) catch @panic("OOM"),
Expand All @@ -157,7 +147,17 @@ pub fn init(options: StepOptions) Step {
.dependants = .{},
.state = .precheck_unstarted,
.max_rss = options.max_rss,
.debug_stack_trace = addresses,
.debug_stack_trace = blk: {
const addresses = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM");
@memset(addresses, 0);
const first_ret_addr = options.first_ret_addr orelse @returnAddress();
var stack_trace = std.builtin.StackTrace{
.instruction_addresses = addresses,
.index = 0,
};
std.debug.captureStackTrace(first_ret_addr, &stack_trace);
break :blk addresses;
},
.result_error_msgs = .{},
.result_error_bundle = std.zig.ErrorBundle.empty,
.result_cached = false,
Expand Down Expand Up @@ -199,14 +199,14 @@ pub fn dependOn(self: *Step, other: *Step) void {
self.dependencies.append(other) catch @panic("OOM");
}

pub fn getStackTrace(s: *Step) std.builtin.StackTrace {
const stack_addresses = &s.debug_stack_trace;
pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace {
var len: usize = 0;
while (len < n_debug_stack_frames and stack_addresses[len] != 0) {
while (len < s.debug_stack_trace.len and s.debug_stack_trace[len] != 0) {
len += 1;
}
return .{
.instruction_addresses = stack_addresses,

return if (len == 0) null else .{
.instruction_addresses = s.debug_stack_trace,
.index = len,
};
}
Expand All @@ -231,25 +231,29 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
}

/// For debugging purposes, prints identifying information about this Step.
pub fn dump(step: *Step) void {
std.debug.getStderrMutex().lock();
defer std.debug.getStderrMutex().unlock();

const stderr = std.io.getStdErr();
const w = stderr.writer();
const tty_config = std.io.tty.detectConfig(stderr);
pub fn dump(step: *Step, file: std.fs.File) void {
const w = file.writer();
const tty_config = std.io.tty.detectConfig(file);
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
@errorName(err),
}) catch {};
return;
};
const ally = debug_info.allocator;
w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
std.debug.writeStackTrace(step.getStackTrace(), w, ally, debug_info, tty_config) catch |err| {
stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
return;
};
if (step.getStackTrace()) |stack_trace| {
w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
std.debug.writeStackTrace(stack_trace, w, ally, debug_info, tty_config) catch |err| {
w.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
return;
};
} else {
const field = "debug_stack_frames_count";
comptime assert(@hasField(Build, field));
tty_config.setColor(w, .yellow) catch {};
w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
tty_config.setColor(w, .reset) catch {};
}
}

const Step = @This();
Expand Down

0 comments on commit a1049d4

Please sign in to comment.