| 578 | // --- Static callbacks (Windows API requires function pointers) --- |
| 579 | |
| 580 | static LONG WINAPI exception_handler_callback(EXCEPTION_POINTERS* ExceptionInfo) { |
| 581 | DWORD code = ExceptionInfo->ExceptionRecord->ExceptionCode; |
| 582 | |
| 583 | if (!is_fatal_exception(code)) { |
| 584 | return EXCEPTION_CONTINUE_SEARCH; |
| 585 | } |
| 586 | |
| 587 | // Prevent recursion if handler crashes |
| 588 | static volatile LONG already_dumping = 0; |
| 589 | if (InterlockedExchange(&already_dumping, 1) != 0) { |
| 590 | return EXCEPTION_CONTINUE_SEARCH; |
| 591 | } |
| 592 | |
| 593 | auto& self = instance(); |
| 594 | self.begin_crash_dump(); |
| 595 | |
| 596 | printf("\n=== INTERNAL EXCEPTION HANDLER (WINDOWS) ===\n"); |
| 597 | printf("Exception caught: 0x%08lx at address 0x%p\n", |
| 598 | code, ExceptionInfo->ExceptionRecord->ExceptionAddress); |
| 599 | |
| 600 | print_exception_type(code, ExceptionInfo->ExceptionRecord); |
| 601 | |
| 602 | self.print_stacktrace_from_context(ExceptionInfo->ContextRecord); |
| 603 | |
| 604 | printf("=== END INTERNAL HANDLER ===\n\n"); |
| 605 | |
| 606 | self.end_crash_dump(); |
| 607 | |
| 608 | printf("Uninstalling exception handler, passing exception to external debugger...\n"); |
| 609 | fflush(stdout); |
| 610 | |
| 611 | SetUnhandledExceptionFilter(NULL); |
| 612 | |
| 613 | return EXCEPTION_CONTINUE_SEARCH; |
| 614 | } |
| 615 | |
| 616 | static void signal_handler_callback(int sig) { |
| 617 | // Prevent recursion if handler crashes |
nothing calls this directly
no test coverage detected