From 6d23d91aa5cd82e25dc848748f9e401026c69c15 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Fri, 23 Jan 2026 12:09:47 +0800 Subject: [PATCH 1/4] Capture the stack trace on the crash handler report --- src/crash_handler.zig | 46 ++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/crash_handler.zig b/src/crash_handler.zig index 772cd508..f7063042 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -54,7 +54,7 @@ pub noinline fn crash( std.debug.dumpCurrentStackTraceToWriter(begin_addr, writer) catch abort(); } - report(reason) catch {}; + report(reason, begin_addr) catch {}; }, 1 => { panic_level = 2; @@ -68,7 +68,7 @@ pub noinline fn crash( abort(); } -fn report(reason: []const u8) !void { +fn report(reason: []const u8, begin_addr: usize) !void { if (@import("telemetry/telemetry.zig").isDisabled()) { return; } @@ -76,24 +76,42 @@ fn report(reason: []const u8) !void { var curl_path: [2048]u8 = undefined; const curl_path_len = curlPath(&curl_path) orelse return; - var args_buffer: [4096]u8 = undefined; - var writer: std.Io.Writer = .fixed(&args_buffer); - - try writer.print("https://crash.lightpanda.io/c?v={s}&r=", .{lp.build_config.git_commit}); - for (reason) |b| { - switch (b) { - 'A'...'Z', 'a'...'z', '0'...'9', '-', '.', '_' => try writer.writeByte(b), - ' ' => try writer.writeByte('+'), - else => try writer.writeByte('!'), // some weird character, that we shouldn't have, but that'll we'll replace with a weird (bur url-safe) character + var url_buffer: [4096]u8 = undefined; + const url = blk: { + var writer: std.Io.Writer = .fixed(&url_buffer); + try writer.print("http://localhost:1234/c?v={s}&r=", .{lp.build_config.git_commit}); + for (reason) |b| { + switch (b) { + 'A'...'Z', 'a'...'z', '0'...'9', '-', '.', '_' => try writer.writeByte(b), + ' ' => try writer.writeByte('+'), + else => try writer.writeByte('!'), // some weird character, that we shouldn't have, but that'll we'll replace with a weird (bur url-safe) character + } } - } - try writer.writeByte(0); - const url = writer.buffered(); + try writer.writeByte(0); + 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 + std.debug.dumpCurrentStackTraceToWriter(begin_addr, &writer) catch {}; + var written = writer.buffered(); + if (written.len == 0) { + break :blk "???"; + } + // overwrite the last character with our null terminator, safest since + // our buffer could be full at this point + written[written.len] = 0; + break :blk written[0..written.len + 1]; + }; var argv = [_:null]?[*:0]const u8{ curl_path[0..curl_path_len :0], "-fsSL", + "-H", "Content-Type: application/octet-stream", + "--data-binary", + stack[0..stack.len - 1 : 0], url[0 .. url.len - 1 :0], }; From 67cff5af8b6b4d4434b7ca9c53a09360ba53b984 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Fri, 23 Jan 2026 12:11:09 +0800 Subject: [PATCH 2/4] zig fmt --- src/browser/js/Context.zig | 4 ++-- src/crash_handler.zig | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/browser/js/Context.zig b/src/browser/js/Context.zig index de24fdb1..801ba782 100644 --- a/src/browser/js/Context.zig +++ b/src/browser/js/Context.zig @@ -872,7 +872,7 @@ pub fn startHeapProfiler(self: *Context) void { self.heap_profiler = heap_profiler; } -pub fn stopHeapProfiler(self: *Context) !struct{[]const u8, []const u8} { +pub fn stopHeapProfiler(self: *Context) !struct { []const u8, []const u8 } { var ls: js.Local.Scope = undefined; self.localScope(&ls); defer ls.deinit(); @@ -893,5 +893,5 @@ pub fn stopHeapProfiler(self: *Context) !struct{[]const u8, []const u8} { break :blk try ls.local.jsStringToZig(string_handle, .{}); }; - return .{allocating, snapshot}; + return .{ allocating, snapshot }; } diff --git a/src/crash_handler.zig b/src/crash_handler.zig index f7063042..ca24cf31 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -103,15 +103,16 @@ fn report(reason: []const u8, begin_addr: usize) !void { // overwrite the last character with our null terminator, safest since // our buffer could be full at this point written[written.len] = 0; - break :blk written[0..written.len + 1]; + break :blk written[0 .. written.len + 1]; }; var argv = [_:null]?[*:0]const u8{ curl_path[0..curl_path_len :0], "-fsSL", - "-H", "Content-Type: application/octet-stream", + "-H", + "Content-Type: application/octet-stream", "--data-binary", - stack[0..stack.len - 1 : 0], + stack[0 .. stack.len - 1 :0], url[0 .. url.len - 1 :0], }; From cafa4f51736e9333b215090ab2d7d3f3a5e58fbd Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Fri, 23 Jan 2026 18:58:40 +0800 Subject: [PATCH 3/4] correct crash report host --- src/crash_handler.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crash_handler.zig b/src/crash_handler.zig index ca24cf31..e9d30e95 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -79,7 +79,7 @@ fn report(reason: []const u8, begin_addr: usize) !void { var url_buffer: [4096]u8 = undefined; const url = blk: { var writer: std.Io.Writer = .fixed(&url_buffer); - try writer.print("http://localhost:1234/c?v={s}&r=", .{lp.build_config.git_commit}); + try writer.print("https://crash.lightpanda.io/c?v={s}&r=", .{lp.build_config.git_commit}); for (reason) |b| { switch (b) { 'A'...'Z', 'a'...'z', '0'...'9', '-', '.', '_' => try writer.writeByte(b), From 90d23abe189b7ca1d6f9ccde8daf6a12229a489c Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Sat, 24 Jan 2026 07:50:51 +0800 Subject: [PATCH 4/4] fix null-byte --- src/crash_handler.zig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/crash_handler.zig b/src/crash_handler.zig index e9d30e95..57d5e437 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -96,14 +96,14 @@ fn report(reason: []const u8, begin_addr: usize) !void { const stack = blk: { var writer: std.Io.Writer = .fixed(stack_buffer[0..4095]); // reserve 1 space std.debug.dumpCurrentStackTraceToWriter(begin_addr, &writer) catch {}; - var written = writer.buffered(); + const written = writer.buffered(); if (written.len == 0) { break :blk "???"; } - // overwrite the last character with our null terminator, safest since - // our buffer could be full at this point - written[written.len] = 0; - break :blk written[0 .. written.len + 1]; + // 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]; }; var argv = [_:null]?[*:0]const u8{