summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig21
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);
}
};