From b2cdd8ee719961b2f037f20bf0f88fad94ca73b4 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 6 Jul 2026 22:00:39 -0300 Subject: fix: every external-scanner grammar crashed pardes on parse (rust/cpp/python/...; e.g. opening agave cpi.rs or any tracy .cpp), Debug AND ReleaseSafe. Root cause: clang -fsanitize=function (in zig's default C UBSan set) traps at the runtime's indirect call of the scanner because grammars declare external_scanner_create() with EMPTY PARENS — a K&R non-prototype whose type hash differs from the void*(*)(void) pointer type. The ud1 trap lands on a bogus inlined line (stack.c:746), which cost the diagnosis a detour through rr (its gdbserver dies replaying past the task exit — core dump + coredumpctl worked; ud1 0x6(%eax) = SanitizerHandler kind 6 = function_type_mismatch; scanner-less c/zig grammars never crashed). Fix per review direction: -fno-sanitize=function on the grammar TUs in build.zig — uninstrumented callees make the runtime's call-site checks skip; the rest of UBSan stays live. Second half: fatal signals (SIGILL/SEGV/BUS/FPE) never run defers and bypassed the panic hook, leaving the terminal raw after a crash — root.debug.handleSegfault override now runs vaxis.recover() before std.debug.defaultHandleSegfault, verified in a raw pty (kill -ILL $PPID: rmcup + mouse resets precede the trace). Verified: rust/cpp/python opens work with real highlighting (snapstyle: keywords/strings/comments colored), agave cpi.js 2.7k-line open fine, suite 30/30, ReleaseSafe build opens rust identically. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/main.zig b/src/main.zig index 56d04669..5275ea28 100644 --- a/src/main.zig +++ b/src/main.zig @@ -28,6 +28,16 @@ pub const panic = if (is_emscripten) std.debug.FullPanic(std.debug.defaultPanic) } }.call); +// 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(); + return std.debug.defaultHandleSegfault(addr, name, opt_ctx); + } +}; + const help_text = \\Usage: pardes [options] \\ -- cgit v1.3