| ... | @@ -228,9 +228,32 @@ pub fn assert(ok: bool) void { | ... | @@ -228,9 +228,32 @@ pub fn assert(ok: bool) void { |
| 228 | | 228 | |
| 229 | pub fn panic(comptime format: []const u8, args: anytype) noreturn { | 229 | pub 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_address | 231 | |
| 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. |
| | 237 | pub 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 | } |
| 235 | | 258 | |
| 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. |
| 245 | threadlocal var panic_stage: usize = 0; | 268 | threadlocal var panic_stage: usize = 0; |
| 246 | | 269 | |
| 247 | pub 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) |
| | 272 | pub fn panicImpl(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, msg: []const u8) noreturn { |
| 248 | @setCold(true); | 273 | @setCold(true); |
| 249 | | 274 | |
| 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 | } |