authorgravatar for greenblattryan@gmail.comrgreenblatt <greenblattryan@gmail.com> 2021-06-26 11:28:03-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-28 13:10:10-04:00
log754ea118bc7192b75c337ae95ad54dbe619dea56
treece07428dfd700a88d83377d42c4a76471566e4a0
parent1cc5d4e758a95be373756e7c32f9bb46d21633c9

improve panic hierarchy by always using builtin.panic


2 files changed, 39 insertions(+), 9 deletions(-)

lib/std/builtin.zig+1-1
...@@ -710,7 +710,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn...@@ -710,7 +710,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
710 },710 },
711 else => {711 else => {
712 const first_trace_addr = @returnAddress();712 const first_trace_addr = @returnAddress();
713 std.debug.panicExtra(error_return_trace, first_trace_addr, "{s}", .{msg});713 std.debug.panicImpl(error_return_trace, first_trace_addr, msg);
714 },714 },
715 }715 }
716}716}
lib/std/debug.zig+38-8
...@@ -228,9 +228,32 @@ pub fn assert(ok: bool) void {...@@ -228,9 +228,32 @@ pub fn assert(ok: bool) void {
228228
229pub fn panic(comptime format: []const u8, args: anytype) noreturn {229pub fn panic(comptime format: []const u8, args: anytype) noreturn {
230 @setCold(true);230 @setCold(true);
231 // TODO: remove conditional once wasi / LLVM defines __builtin_return_address231
232 const first_trace_addr = if (native_os == .wasi) null else @returnAddress();232 panicExtra(null, format, args);
233 panicExtra(null, first_trace_addr, format, args);233}
234
235/// `panicExtra` is useful when you want to print out an `@errorReturnTrace`
236/// and also print out some values.
237pub fn panicExtra(
238 trace: ?*builtin.StackTrace,
239 comptime format: []const u8,
240 args: anytype,
241) noreturn {
242 @setCold(true);
243
244 const size = 0x1000;
245 const trunc_msg = "(msg truncated)";
246 var buf: [size + trunc_msg.len]u8 = undefined;
247 // a minor annoyance with this is that it will result in the NoSpaceLeft
248 // error being part of the @panic stack trace (but that error should
249 // only happen rarely)
250 const msg = std.fmt.bufPrint(buf[0..size], format, args) catch |err| switch (err) {
251 std.fmt.BufPrintError.NoSpaceLeft => blk: {
252 std.mem.copy(u8, buf[size..], trunc_msg);
253 break :blk &buf;
254 },
255 };
256 builtin.panic(msg, trace);
234}257}
235258
236/// Non-zero whenever the program triggered a panic.259/// Non-zero whenever the program triggered a panic.
...@@ -244,7 +267,9 @@ var panic_mutex = std.Thread.Mutex{};...@@ -244,7 +267,9 @@ var panic_mutex = std.Thread.Mutex{};
244/// This is used to catch and handle panics triggered by the panic handler.267/// This is used to catch and handle panics triggered by the panic handler.
245threadlocal var panic_stage: usize = 0;268threadlocal var panic_stage: usize = 0;
246269
247pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: anytype) noreturn {270// `panicImpl` could be useful in implementing a custom panic handler which
271// calls the default handler (on supported platforms)
272pub fn panicImpl(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, msg: []const u8) noreturn {
248 @setCold(true);273 @setCold(true);
249274
250 if (enable_segfault_handler) {275 if (enable_segfault_handler) {
...@@ -271,7 +296,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c...@@ -271,7 +296,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
271 const current_thread_id = std.Thread.getCurrentId();296 const current_thread_id = std.Thread.getCurrentId();
272 stderr.print("thread {} panic: ", .{current_thread_id}) catch os.abort();297 stderr.print("thread {} panic: ", .{current_thread_id}) catch os.abort();
273 }298 }
274 stderr.print(format ++ "\n", args) catch os.abort();299 stderr.print("{s}\n", .{msg}) catch os.abort();
275 if (trace) |t| {300 if (trace) |t| {
276 dumpStackTrace(t.*);301 dumpStackTrace(t.*);
277 }302 }
...@@ -1626,9 +1651,14 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, comptime msg: u...@@ -1626,9 +1651,14 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, comptime msg: u
1626 os.abort();1651 os.abort();
1627 } else {1652 } else {
1628 switch (msg) {1653 switch (msg) {
1629 0 => panicExtra(null, exception_address, format.?, .{}),1654 0 => panicImpl(null, exception_address, format.?),
1630 1 => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", .{info.ExceptionRecord.ExceptionInformation[1]}),1655 1 => {
1631 2 => panicExtra(null, exception_address, "Illegal Instruction", .{}),1656 const format_item = "Segmentation fault at address 0x{x}";
1657 var buf: [format_item.len + 64]u8 = undefined; // 64 is arbitrary, but sufficiently large
1658 const to_print = std.fmt.bufPrint(buf[0..buf.len], format_item, .{info.ExceptionRecord.ExceptionInformation[1]}) catch unreachable;
1659 panicImpl(null, exception_address, to_print);
1660 },
1661 2 => panicImpl(null, exception_address, "Illegal Instruction"),
1632 else => unreachable,1662 else => unreachable,
1633 }1663 }
1634 }1664 }