diff --git a/lib/std/debug.zig b/lib/std/debug.zig index c50cdc2df8c9..b09546476288 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1689,6 +1689,12 @@ pub fn maybeEnableSegfaultHandler() void { var windows_segfault_handle: ?windows.HANDLE = null; +pub fn updateSegfaultHandler(act: ?*const os.Sigaction) error{OperationNotSupported}!void { + try os.sigaction(os.SIG.SEGV, act, null); + try os.sigaction(os.SIG.ILL, act, null); + try os.sigaction(os.SIG.BUS, act, null); +} + /// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); pub fn attachSegfaultHandler() void { if (!have_segfault_handling_support) { @@ -1704,9 +1710,9 @@ pub fn attachSegfaultHandler() void { .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), }; - os.sigaction(os.SIG.SEGV, &act, null); - os.sigaction(os.SIG.ILL, &act, null); - os.sigaction(os.SIG.BUS, &act, null); + updateSegfaultHandler(&act) catch { + @panic("unable to install segfault handler, maybe adjust have_segfault_handling_support in std/debug.zig"); + }; } fn resetSegfaultHandler() void { @@ -1722,9 +1728,8 @@ fn resetSegfaultHandler() void { .mask = os.empty_sigset, .flags = 0, }; - os.sigaction(os.SIG.SEGV, &act, null); - os.sigaction(os.SIG.ILL, &act, null); - os.sigaction(os.SIG.BUS, &act, null); + // do nothing if an error happens to avoid a double-panic + updateSegfaultHandler(&act) catch {}; } fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { diff --git a/lib/std/os.zig b/lib/std/os.zig index 0fabc9bff568..87fe6c7f7ba4 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -5521,11 +5521,10 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void { } /// Examine and change a signal action. -pub fn sigaction(sig: u6, act: ?*const Sigaction, oact: ?*Sigaction) void { +pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) error{OperationNotSupported}!void { switch (errno(system.sigaction(sig, act, oact))) { .SUCCESS => return, - .FAULT => unreachable, - .INVAL => unreachable, + .INVAL, .NOSYS => return error.OperationNotSupported, else => unreachable, } } diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index f6077cb38ece..7f301826b1c6 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -772,16 +772,16 @@ test "sigaction" { }; var old_sa: os.Sigaction = undefined; // Install the new signal handler. - os.sigaction(os.SIG.USR1, &sa, null); + try os.sigaction(os.SIG.USR1, &sa, null); // Check that we can read it back correctly. - os.sigaction(os.SIG.USR1, null, &old_sa); + try os.sigaction(os.SIG.USR1, null, &old_sa); try testing.expectEqual(S.handler, old_sa.handler.sigaction.?); try testing.expect((old_sa.flags & os.SA.SIGINFO) != 0); // Invoke the handler. try os.raise(os.SIG.USR1); try testing.expect(signal_test_failed == false); // Check if the handler has been correctly reset to SIG_DFL - os.sigaction(os.SIG.USR1, null, &old_sa); + try os.sigaction(os.SIG.USR1, null, &old_sa); try testing.expectEqual(os.SIG.DFL, old_sa.handler.sigaction); } diff --git a/src/crash_report.zig b/src/crash_report.zig index 7e72c648005d..472e52b04d33 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -175,9 +175,9 @@ pub fn attachSegfaultHandler() void { .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), }; - os.sigaction(os.SIG.SEGV, &act, null); - os.sigaction(os.SIG.ILL, &act, null); - os.sigaction(os.SIG.BUS, &act, null); + debug.updateSegfaultHandler(&act) catch { + @panic("unable to install segfault handler, maybe adjust have_segfault_handling_support in std/debug.zig"); + }; } fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {