Merge pull request #1655 from lightpanda-io/crash_report_args
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled

Include assertion args in crash report
This commit is contained in:
Karl Seguin
2026-02-25 18:36:24 +08:00
committed by GitHub
2 changed files with 27 additions and 10 deletions

View File

@@ -628,8 +628,13 @@ pub const Script = struct {
node: std.DoublyLinkedList.Node,
script_element: ?*Element.Html.Script,
manager: *ScriptManager,
// for debugging a rare production issue
header_callback_called: bool = false,
// for debugging a rare production issue
debug_transfer_id: u32 = 0,
const Kind = enum {
module,
javascript,
@@ -697,8 +702,14 @@ pub const Script = struct {
// temp debug, trying to figure out why the next assert sometimes
// fails. Is the buffer just corrupt or is headerCallback really
// being called twice?
lp.assert(self.header_callback_called == false, "ScriptManager.Header recall", .{});
lp.assert(self.header_callback_called == false, "ScriptManager.Header recall", .{
.thd = transfer._header_done_called,
.t1 = self.debug_transfer_id,
.t2 = transfer.id,
.tries = transfer._tries,
});
self.header_callback_called = true;
self.debug_transfer_id = transfer.id;
}
lp.assert(self.source.remote.capacity == 0, "ScriptManager.Header buffer", .{ .capacity = self.source.remote.capacity });

View File

@@ -57,7 +57,7 @@ pub noinline fn crash(
std.debug.dumpCurrentStackTraceToWriter(begin_addr, writer) catch abort();
}
report(reason, begin_addr) catch {};
report(reason, begin_addr, args) catch {};
},
1 => {
panic_level = 2;
@@ -71,7 +71,7 @@ pub noinline fn crash(
abort();
}
fn report(reason: []const u8, begin_addr: usize) !void {
fn report(reason: []const u8, begin_addr: usize, args: anytype) !void {
if (comptime IS_DEBUG) {
return;
}
@@ -99,18 +99,24 @@ fn report(reason: []const u8, begin_addr: usize) !void {
break :blk writer.buffered();
};
var stack_buffer: [4096]u8 = undefined;
const stack = blk: {
var writer: std.Io.Writer = .fixed(stack_buffer[0..4095]); // reserve 1 space
var body_buffer: [8192]u8 = undefined;
const body = blk: {
var writer: std.Io.Writer = .fixed(body_buffer[0..8191]); // reserve 1 space
inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |f| {
writer.writeAll(f.name ++ ": ") catch break;
@import("log.zig").writeValue(.pretty, @field(args, f.name), &writer) catch {};
writer.writeByte('\n') catch {};
}
std.debug.dumpCurrentStackTraceToWriter(begin_addr, &writer) catch {};
const written = writer.buffered();
if (written.len == 0) {
break :blk "???";
}
// Overwrite the last character with our null terminator
// stack_buffer always has to be > written
stack_buffer[written.len] = 0;
break :blk stack_buffer[0 .. written.len + 1];
// body_buffer always has to be > written
body_buffer[written.len] = 0;
break :blk body_buffer[0 .. written.len + 1];
};
var argv = [_:null]?[*:0]const u8{
@@ -119,7 +125,7 @@ fn report(reason: []const u8, begin_addr: usize) !void {
"-H",
"Content-Type: application/octet-stream",
"--data-binary",
stack[0 .. stack.len - 1 :0],
body[0 .. body.len - 1 :0],
url[0 .. url.len - 1 :0],
};