From 111165513156d5732d85e5ccb52b9d8bded41ffa Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 6 Jan 2026 10:50:45 +0000 Subject: [PATCH] std: block cancelation in default panic and segfault handlers It doesn't make any sense for a task to be canceled while it's panicking. As a happy accident, this also solves some cases where safety panics in `Io.Threaded` would cause stack traces not to print due to invalid thread-local state: when cancelation is blocked, `Io.Threaded` doesn't consult said thread-local state at all. For instance, try inserting a panic just after a call to `Syscall.start()` in `Io.Threaded`, and then call the `Io` function in question from a `concurrent` task. Before this PR, the stack trace fails to print, because the panic handler sees the thread-local cancelation state in an unexpected state, leading to a recursive panic. After this PR, the stack trace prints fine. --- lib/std/debug.zig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 0f151447fc56b4d7afdde22709b2bc0fe414d554..8b76e307a154654c132b83480f5abf19f5243fcd 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -532,6 +532,10 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn { else => {}, } + // Don't try to cancel during a panic. No need to re-enable cancelation, + // because the panic handler doesn't return. + _ = std.Options.debug_io.swapCancelProtection(.blocked); + if (enable_segfault_handler) { // If a segfault happens while panicking, we want it to actually segfault, not trigger // the handler. @@ -1533,6 +1537,10 @@ fn handleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noret } pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noreturn { + // Don't try to cancel during a segfault. No need to re-enable cancelation, + // because the segfault handler doesn't return. + _ = std.Options.debug_io.swapCancelProtection(.blocked); + // There is very similar logic to the following in `defaultPanic`. switch (panic_stage) { 0 => { -- 2.54.0