diff options
Diffstat (limited to 'std')
| -rw-r--r-- | std/debug.zig | 62 | ||||
| -rw-r--r-- | std/os/windows/kernel32.zig | 1 | ||||
| -rw-r--r-- | std/special/start.zig | 14 |
3 files changed, 47 insertions, 30 deletions
diff --git a/std/debug.zig b/std/debug.zig index d81e62901a..7d1fd6ce47 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -12,6 +12,7 @@ const coff = std.coff; const pdb = std.pdb; const ArrayList = std.ArrayList; const builtin = @import("builtin"); +const root = @import("root"); const maxInt = std.math.maxInt; const File = std.fs.File; const windows = std.os.windows; @@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { @setCold(true); + if (enable_segfault_handler) { + // If a segfault happens while panicking, we want it to actually segfault, not trigger + // the handler. + resetSegfaultHandler(); + } + if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { // Panicked during a panic. @@ -2312,39 +2319,58 @@ fn getDebugInfoAllocator() *mem.Allocator { /// Whether or not the current target can print useful debug information when a segfault occurs. pub const have_segfault_handling_support = (builtin.arch == builtin.Arch.x86_64 and builtin.os == .linux) or builtin.os == .windows; +pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) + root.enable_segfault_handler +else + runtime_safety and have_segfault_handling_support; + +pub fn maybeEnableSegfaultHandler() void { + if (enable_segfault_handler) { + std.debug.attachSegfaultHandler(); + } +} + +var windows_segfault_handle: ?windows.HANDLE = null; /// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); pub fn attachSegfaultHandler() void { if (!have_segfault_handling_support) { @compileError("segfault handler not supported for this target"); } - switch (builtin.os) { - .linux => { - var act = os.Sigaction{ - .sigaction = handleSegfaultLinux, - .mask = os.empty_sigset, - .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), - }; - - os.sigaction(os.SIGSEGV, &act, null); - }, - .windows => { - _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); - }, - else => unreachable, + if (windows.is_the_target) { + windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); + return; } + var act = os.Sigaction{ + .sigaction = handleSegfaultLinux, + .mask = os.empty_sigset, + .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), + }; + + os.sigaction(os.SIGSEGV, &act, null); } -extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn { - // Reset to the default handler so that if a segfault happens in this handler it will crash - // the process. Also when this handler returns, the original instruction will be repeated - // and the resulting segfault will crash the process rather than continually dump stack traces. +fn resetSegfaultHandler() void { + if (windows.is_the_target) { + if (windows_segfault_handle) |handle| { + assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0); + windows_segfault_handle = null; + } + return; + } var act = os.Sigaction{ .sigaction = os.SIG_DFL, .mask = os.empty_sigset, .flags = 0, }; os.sigaction(os.SIGSEGV, &act, null); +} + +extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn { + // Reset to the default handler so that if a segfault happens in this handler it will crash + // the process. Also when this handler returns, the original instruction will be repeated + // and the resulting segfault will crash the process rather than continually dump stack traces. + resetSegfaultHandler(); const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]); diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig index e4edc349ab..2ae73ad45a 100644 --- a/std/os/windows/kernel32.zig +++ b/std/os/windows/kernel32.zig @@ -1,6 +1,7 @@ usingnamespace @import("bits.zig"); pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void; +pub extern "kernel32" stdcallcc fn RemoveVectoredExceptionHandler(Handle: HANDLE) c_ulong; pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL; diff --git a/std/special/start.zig b/std/special/start.zig index 30298669e3..f8a018e0ae 100644 --- a/std/special/start.zig +++ b/std/special/start.zig @@ -24,16 +24,6 @@ comptime { } } -fn enableSegfaultHandler() void { - const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) - root.enable_segfault_handler - else - std.debug.runtime_safety and std.debug.have_segfault_handling_support; - if (enable_segfault_handler) { - std.debug.attachSegfaultHandler(); - } -} - extern fn wasm_freestanding_start() void { _ = callMain(); } @@ -72,7 +62,7 @@ extern fn WinMainCRTStartup() noreturn { _ = @import("start_windows_tls.zig"); } - enableSegfaultHandler(); + std.debug.maybeEnableSegfaultHandler(); std.os.windows.kernel32.ExitProcess(callMain()); } @@ -113,7 +103,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { std.os.argv = argv[0..argc]; std.os.environ = envp; - enableSegfaultHandler(); + std.debug.maybeEnableSegfaultHandler(); return callMain(); } |
