C ++ Error / Exception Handler in a Qt Application with Thread Support in Windows

I want to make a crash / exception handler for my Qt application. The handler already works for me (not included in the code below). The problem with Windows is that it only works if the crash occurs in the same thread where signal() and std::set_terminate() called.

On Linux, it works by default for all threads.

Is there a way to make it work for all application threads on Windows?

 #include "mainwindow.h" #include <QApplication> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <exception> void seg_handler(int sig) { // Crash/exception handling code // ... exit(1); } void std_handler( void ) { seg_handler(1); } int main(int argc, char *argv[]) { signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } 
+6
source share
3 answers

After a lot of research, coupled with a lack of knowledge in Windows, I finally reached a working solution that automatically sets completion functions for new threads.

The trick is to create a dll to handle your failures / exceptions. Your dll implements the reserved DllMain() function. This function receives notifications every time a new thread or process joins the main process. The fdwReason parameter contains information about the event.

  • New thread: DLL_THREAD_ATTACH
  • New process: DLL_PROCESS_ATTACH

Deploy the completion handlers in the dll and call signal() and std::set_terminate() for each thread or process that is running.

 BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) { if (fdwReason==DLL_THREAD_ATTACH) { signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); } if (fdwReason==DLL_PROCESS_ATTACH) { signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); } return TRUE; } 

My handlers look like this:

 #include <windows.h> #include "StackWalker.h" #include <signal.h> #include <DbgHelp.h> #include <iostream> #include <qdebug.h> void seg_handler(int sig) { // Simple callstack unsigned int i; void * stack[ 100 ]; unsigned short frames; SYMBOL_INFO * symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize( process, NULL, TRUE ); frames = CaptureStackBackTrace( 0, 100, stack, NULL ); symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); for( i = 0; i < frames; i++ ) { SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); printf( "%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address ); } free( symbol ); // Detailed callstack/crashinfo StackWalker sw; sw.ShowCallstack(GetCurrentThread()); exit(1); } void std_handler( void ) { seg_handler(1); } 

Handlers above use StackWalker

Edit:

Of course, you also need to add completion handlers to your main thread:

 int main(int argc, char *argv[]) { CALL_LOGGER(); signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); return runapp(argc, argv); } 

Hope this helps someone

-Jakob

+3
source

I suspect SetUnhandledExceptionFilter is a better way to trap on Windows than signal . It is configured globally (so you don’t need a DLL to install a handler in each thread) and does not discard the failure information (is there any way to restore the true SIGSEGV cause, but I don’t immediately know how).

+1
source

According to MSDN :

In a multi-threaded environment, completion functions are supported separately for each thread. Each new thread needs to set its own to stop working. Thus, each thread is responsible for its own termination of processing.

I think you should set it separately for each thread.

0
source

All Articles