From 13b6d0b447a87859900d9685f5524159f7b4bcaf Mon Sep 17 00:00:00 2001 From: patchzyy <64382339+patchzyy@users.noreply.github.com> Date: Mon, 31 Aug 2026 16:28:24 +0200 Subject: [PATCH] Refine SEH crash handling on Windows --- runtime/src/main.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 316220e..2ae8ed8 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -921,6 +921,7 @@ constexpr DWORD kCppExceptionCodeMsvc = 0xE06D7363; // AddressSanitizer uses STATUS_FATAL_APP_EXIT when it detects an error and wants to report it. // We must let ASan's handler run so it can print file/line information. constexpr DWORD kAsanFatalAppExit = 0x40000015; // STATUS_FATAL_APP_EXIT +LONG ReportFatalSehAndExit(EXCEPTION_POINTERS* info); void ReportStructuredException(EXCEPTION_POINTERS* info) { if (!info || !info->ExceptionRecord) { @@ -1022,13 +1023,34 @@ LONG CALLBACK SehLogger(EXCEPTION_POINTERS* info) { info->ExceptionRecord->ExceptionCode == kAsanFatalAppExit) { // ASan reporting - let it print first return EXCEPTION_CONTINUE_SEARCH; } - + // Software-raised exceptions (customer bit set) are used for internal control flow by + // system DLLs (e.g. msxml6 while mscms parses a display colour profile) and are caught + // by their own frame handlers. Only hardware faults are fatal at first chance; anything + // else that truly goes unhandled reaches UnhandledSehFilter. + if ((info->ExceptionRecord->ExceptionCode & 0x20000000u) != 0) { + return EXCEPTION_CONTINUE_SEARCH; + } + return ReportFatalSehAndExit(info); +} + +LONG WINAPI UnhandledSehFilter(EXCEPTION_POINTERS* info) { + if (info == nullptr || info->ExceptionRecord == nullptr) { + return EXCEPTION_CONTINUE_SEARCH; + } + const DWORD code = info->ExceptionRecord->ExceptionCode; + if (code == kCppExceptionCodeGcc || code == kCppExceptionCodeMsvc || code == kAsanFatalAppExit) { + return EXCEPTION_CONTINUE_SEARCH; + } + return ReportFatalSehAndExit(info); +} + +LONG ReportFatalSehAndExit(EXCEPTION_POINTERS* info) { // Guard against re-entrancy: if we crash while reporting, don't recurse static std::atomic_flag s_inCrashHandler = ATOMIC_FLAG_INIT; if (s_inCrashHandler.test_and_set()) { std::_Exit(EXIT_FAILURE); } - + // Report the structured exception with detailed information ReportStructuredException(info); const auto* record = info->ExceptionRecord; @@ -1063,6 +1085,7 @@ LONG CALLBACK SehLogger(EXCEPTION_POINTERS* info) { void InstallSehLogger() { if (!g_vectoredSehHandle) { g_vectoredSehHandle = AddVectoredExceptionHandler(1, SehLogger); + SetUnhandledExceptionFilter(UnhandledSehFilter); } } #else