diff options
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/src/main.zig b/src/main.zig index 60491052..92b59bc2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -53,18 +53,33 @@ fn logFn( // exactly the behaviour that was here before. pub const panic = if (is_emscripten) std.debug.FullPanic(std.debug.defaultPanic) else std.debug.FullPanic(struct { fn call(msg: []const u8, ret_addr: ?usize) noreturn { - @import("vaxis").recover(); - @import("crash.zig").record(msg, ret_addr); + // ONCE. This handler is re-entered whenever something panics while it + // runs, and std's own trace printer does exactly that — `defaultPanic` + // survives its own recursion through a private `panic_stage`, and + // everything up here is in front of that guard. `recover()` is not + // idempotent: it closes the vaxis tty and never clears the global that + // says there is one, so a second call double-closes, which std answers + // with `recoverableOsBugDetected` and an `unreachable` in a Debug + // build. Measured with the crash file in place: one panic left TWO + // records, the real message and then "reached unreachable code" from + // this line under it. + if (!recovering.swap(true, .seq_cst)) @import("vaxis").recover(); + @import("crash.zig").record(msg); std.debug.defaultPanic(msg, ret_addr); } }.call); +/// Whether this process has already restored its terminal — see `panic` above, +/// and note that `debug.handleSegfault` below shares it: a SIGSEGV raised while +/// the panic handler runs must not double-close either. +var recovering: std.atomic.Value(bool) = .init(false); + // Fatal signals (SIGSEGV/SIGILL/SIGBUS/SIGFPE) bypass the panic handler and // no defer/errdefer ever runs — hook std.debug's segfault path the same way // so the terminal is restored before the trace prints. pub const debug = if (is_emscripten) struct {} else struct { pub fn handleSegfault(addr: ?usize, name: []const u8, opt_ctx: anytype) noreturn { - @import("vaxis").recover(); + if (!recovering.swap(true, .seq_cst)) @import("vaxis").recover(); return std.debug.defaultHandleSegfault(addr, name, opt_ctx); } }; |
