49 signal(SIGSEGV, CrashHandler::abortHandler);
53 sa.sa_flags = SA_SIGINFO;
54 sa.sa_sigaction = CrashHandler::abortHandler;
55 sigemptyset( &sa.sa_mask );
58 sigaction( SIGABRT, &sa, NULL );
59 sigaction( SIGSEGV, &sa, NULL );
60 sigaction( SIGBUS, &sa, NULL );
61 sigaction( SIGILL, &sa, NULL );
62 sigaction( SIGFPE, &sa, NULL );
63 sigaction( SIGPIPE, &sa, NULL );
72 void CrashHandler::abortHandler(
int signum)
75 const char* name = NULL;
78 case SIGABRT: name =
"SIGABRT";
break;
79 case SIGSEGV: name =
"SIGSEGV";
break;
80 case SIGILL: name =
"SIGILL";
break;
81 case SIGFPE: name =
"SIGFPE";
break;
86 fprintf( stderr,
"Caught signal %d (%s)\n", signum, name );
88 fprintf( stderr,
"Caught signal %d\n", signum );
91 printStackTrace(stderr, 63);
98 void CrashHandler::abortHandler(
int signum, siginfo_t* si,
void* unused )
101 const char* name = NULL;
104 case SIGABRT: name =
"SIGABRT";
break;
105 case SIGSEGV: name =
"SIGSEGV";
break;
106 case SIGBUS: name =
"SIGBUS";
break;
107 case SIGILL: name =
"SIGILL";
break;
108 case SIGFPE: name =
"SIGFPE";
break;
109 case SIGPIPE: name =
"SIGPIPE";
break;
114 fprintf( stderr,
"Caught signal %d (%s)\n", signum, name );
116 fprintf( stderr,
"Caught signal %d\n", signum );
119 printStackTrace(stderr, 63);
126 void CrashHandler::printStackTrace(FILE *out,
unsigned int max_frames)
128 fprintf(out,
"---- Unhandled Exception: Stack Trace ----\n");
129 ZmqLogger::Instance()->LogToFile(
"---- Unhandled Exception: Stack Trace ----\n");
130 stringstream stack_output;
134 HANDLE process = GetCurrentProcess();
135 HANDLE thread = GetCurrentThread();
138 memset(&context, 0,
sizeof(CONTEXT));
139 context.ContextFlags = CONTEXT_FULL;
140 RtlCaptureContext(&context);
142 SymInitialize(process, NULL, TRUE);
145 STACKFRAME64 stackframe;
146 ZeroMemory(&stackframe,
sizeof(STACKFRAME64));
149 image = IMAGE_FILE_MACHINE_I386;
150 stackframe.AddrPC.Offset = context.Eip;
151 stackframe.AddrPC.Mode = AddrModeFlat;
152 stackframe.AddrFrame.Offset = context.Ebp;
153 stackframe.AddrFrame.Mode = AddrModeFlat;
154 stackframe.AddrStack.Offset = context.Esp;
155 stackframe.AddrStack.Mode = AddrModeFlat;
157 image = IMAGE_FILE_MACHINE_AMD64;
158 stackframe.AddrPC.Offset = context.Rip;
159 stackframe.AddrPC.Mode = AddrModeFlat;
160 stackframe.AddrFrame.Offset = context.Rsp;
161 stackframe.AddrFrame.Mode = AddrModeFlat;
162 stackframe.AddrStack.Offset = context.Rsp;
163 stackframe.AddrStack.Mode = AddrModeFlat;
165 image = IMAGE_FILE_MACHINE_IA64;
166 stackframe.AddrPC.Offset = context.StIIP;
167 stackframe.AddrPC.Mode = AddrModeFlat;
168 stackframe.AddrFrame.Offset = context.IntSp;
169 stackframe.AddrFrame.Mode = AddrModeFlat;
170 stackframe.AddrBStore.Offset = context.RsBSP;
171 stackframe.AddrBStore.Mode = AddrModeFlat;
172 stackframe.AddrStack.Offset = context.IntSp;
173 stackframe.AddrStack.Mode = AddrModeFlat;
177 for (
size_t i = 0; i < max_frames; i++) {
179 BOOL result = StackWalk64(
180 image, process, thread,
181 &stackframe, &context, NULL,
182 SymFunctionTableAccess64, SymGetModuleBase64, NULL);
184 if (i <= 2) {
continue; }
185 if (!result) {
break; }
187 char buffer[
sizeof(SYMBOL_INFO) + MAX_SYM_NAME *
sizeof(TCHAR)];
188 PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
189 symbol->SizeOfStruct =
sizeof(SYMBOL_INFO);
190 symbol->MaxNameLen = MAX_SYM_NAME;
191 WINBOOL found_symbol = SymFromAddr(process, stackframe.AddrPC.Offset, NULL, symbol);
194 printf(
"[%i] %s, address 0x%0X\n", i, symbol->Name, symbol->Address);
195 stack_output << left << setw(30) << symbol->Name <<
" " << setw(40) << std::hex << symbol->Address << std::dec << endl;
197 printf(
"[%i] ???\n", i);
198 stack_output << left << setw(30) <<
"???" << endl;
206 void* addrlist[max_frames+1];
209 unsigned int addrlen = backtrace( addrlist,
sizeof( addrlist ) /
sizeof(
void* ));
213 fprintf(out,
" No stack trace found (addrlen == 0)\n");
214 ZmqLogger::Instance()->LogToFile(
" No stack trace found (addrlen == 0)\n");
221 char** symbollist = backtrace_symbols( addrlist, addrlen );
223 size_t funcnamesize = 1024;
228 for (
unsigned int i = 4; i < addrlen; i++ )
230 char* begin_name = NULL;
231 char* begin_offset = NULL;
232 char* end_offset = NULL;
237 for (
char *p = symbollist[i]; *p; ++p )
239 if (( *p ==
'_' ) && ( *(p-1) ==
' ' ))
241 else if ( *p ==
'+' )
245 if ( begin_name && begin_offset && ( begin_name < begin_offset ))
247 *begin_name++ =
'\0';
248 *begin_offset++ =
'\0';
254 char* ret = abi::__cxa_demangle( begin_name, &funcname[0], &funcnamesize, &status );
258 fprintf( out,
" %-30s %-40s %s\n", symbollist[i], funcname, begin_offset );
259 stack_output << left <<
" " << setw(30) << symbollist[i] <<
" " << setw(40) << funcname <<
" " << begin_offset << endl;
263 fprintf( out,
" %-30s %-38s() %s\n", symbollist[i], begin_name, begin_offset );
264 stack_output << left <<
" " << setw(30) << symbollist[i] <<
" " << setw(38) << begin_name <<
" " << begin_offset << endl;
267 #else // !DARWIN - but is posix 270 for (
char *p = symbollist[i]; *p; ++p )
274 else if ( *p ==
'+' )
276 else if ( *p ==
')' && ( begin_offset || begin_name ))
280 if ( begin_name && end_offset && ( begin_name < end_offset ))
282 *begin_name++ =
'\0';
283 *end_offset++ =
'\0';
285 *begin_offset++ =
'\0';
291 char* ret = abi::__cxa_demangle( begin_name, funcname, &funcnamesize, &status );
292 char* fname = begin_name;
298 fprintf( out,
" %-30s ( %-40s + %-6s) %s\n", symbollist[i], fname, begin_offset, end_offset );
299 stack_output << left <<
" " << setw(30) << symbollist[i] <<
" " << setw(40) << fname <<
" " << begin_offset <<
" " << end_offset << endl;
302 fprintf( out,
" %-30s ( %-40s %-6s) %s\n", symbollist[i], fname,
"", end_offset );
303 stack_output << left <<
" " << setw(30) << symbollist[i] <<
" " << setw(40) << fname <<
" " << end_offset << endl;
306 #endif // !DARWIN - but is posix 309 fprintf(out,
" %-40s\n", symbollist[i]);
310 stack_output << left <<
" " << setw(40) << symbollist[i] << endl;
319 ZmqLogger::Instance()->LogToFile(stack_output.str());
321 fprintf(out,
"---- End of Stack Trace ----\n");
322 ZmqLogger::Instance()->LogToFile(
"---- End of Stack Trace ----\n");
This class is designed to catch exceptions thrown by libc (SIGABRT, SIGSEGV, SIGILL, SIGFPE)
This namespace is the default namespace for all code in the openshot library.
Header file for CrashHandler class.