Improve exception handler: detect read or write on SIGSEGV (linux only), create more suitable core dump, reduce usage of fprintf()
This commit is contained in:
parent
149fe74d9d
commit
5786be99c5
|
@ -35,8 +35,14 @@
|
||||||
|
|
||||||
#if !defined(NO_UNIX_SIGNAL_HANDLING) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__OS2__)
|
#if !defined(NO_UNIX_SIGNAL_HANDLING) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__OS2__)
|
||||||
#define USE_UNIX_SIGNAL_HANDLING
|
#define USE_UNIX_SIGNAL_HANDLING
|
||||||
#include <signal.h>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ucontext.h>
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(NO_UNIX_BACKTRACE_SUPPORT) && defined(USE_UNIX_SIGNAL_HANDLING) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__NetBSD__) && !defined(__SVR4)
|
#if !defined(NO_UNIX_BACKTRACE_SUPPORT) && defined(USE_UNIX_SIGNAL_HANDLING) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__NetBSD__) && !defined(__SVR4)
|
||||||
|
@ -296,9 +302,21 @@ static void print_stacktrace(FILE* f, bool demangling)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry pointer for signal handlers
|
* Entry pointer for signal handlers
|
||||||
|
* It uses functions which are not safe to be called from a signal handler,
|
||||||
|
* but when ending up here something went terribly wrong anyway.
|
||||||
|
* And all which is left is just printing some information and terminate.
|
||||||
*/
|
*/
|
||||||
static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*/)
|
static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
||||||
{
|
{
|
||||||
|
int type = -1;
|
||||||
|
pid_t killid = getpid();
|
||||||
|
const ucontext_t* uc = reinterpret_cast<const ucontext_t*>(context);
|
||||||
|
#ifdef __linux__
|
||||||
|
killid = (pid_t) syscall(SYS_gettid);
|
||||||
|
if (uc) {
|
||||||
|
type = (int)uc->uc_mcontext.gregs[REG_ERR] & 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
const char * const signame = signal_name(signo);
|
const char * const signame = signal_name(signo);
|
||||||
const char * const sigtext = strsignal(signo);
|
const char * const sigtext = strsignal(signo);
|
||||||
bool bPrintCallstack=true;
|
bool bPrintCallstack=true;
|
||||||
|
@ -311,22 +329,22 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
|
||||||
case SIGBUS:
|
case SIGBUS:
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case BUS_ADRALN: // invalid address alignment
|
case BUS_ADRALN: // invalid address alignment
|
||||||
fprintf(f, " - BUS_ADRALN");
|
fputs(" - BUS_ADRALN", f);
|
||||||
break;
|
break;
|
||||||
case BUS_ADRERR: // nonexistent physical address
|
case BUS_ADRERR: // nonexistent physical address
|
||||||
fprintf(f, " - BUS_ADRERR");
|
fputs(" - BUS_ADRERR", f);
|
||||||
break;
|
break;
|
||||||
case BUS_OBJERR: // object-specific hardware error
|
case BUS_OBJERR: // object-specific hardware error
|
||||||
fprintf(f, " - BUS_OBJERR");
|
fputs(" - BUS_OBJERR", f);
|
||||||
break;
|
break;
|
||||||
#ifdef BUS_MCEERR_AR
|
#ifdef BUS_MCEERR_AR
|
||||||
case BUS_MCEERR_AR: // Hardware memory error consumed on a machine check;
|
case BUS_MCEERR_AR: // Hardware memory error consumed on a machine check;
|
||||||
fprintf(f, " - BUS_MCEERR_AR");
|
fputs(" - BUS_MCEERR_AR", f);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUS_MCEERR_AO
|
#ifdef BUS_MCEERR_AO
|
||||||
case BUS_MCEERR_AO: // Hardware memory error detected in process but not consumed
|
case BUS_MCEERR_AO: // Hardware memory error detected in process but not consumed
|
||||||
fprintf(f, " - BUS_MCEERR_AO");
|
fputs(" - BUS_MCEERR_AO", f);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -338,28 +356,28 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case FPE_INTDIV: // integer divide by zero
|
case FPE_INTDIV: // integer divide by zero
|
||||||
fprintf(f, " - FPE_INTDIV");
|
fputs(" - FPE_INTDIV", f);
|
||||||
break;
|
break;
|
||||||
case FPE_INTOVF: // integer overflow
|
case FPE_INTOVF: // integer overflow
|
||||||
fprintf(f, " - FPE_INTOVF");
|
fputs(" - FPE_INTOVF", f);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTDIV: // floating-point divide by zero
|
case FPE_FLTDIV: // floating-point divide by zero
|
||||||
fprintf(f, " - FPE_FLTDIV");
|
fputs(" - FPE_FLTDIV", f);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTOVF: // floating-point overflow
|
case FPE_FLTOVF: // floating-point overflow
|
||||||
fprintf(f, " - FPE_FLTOVF");
|
fputs(" - FPE_FLTOVF", f);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTUND: // floating-point underflow
|
case FPE_FLTUND: // floating-point underflow
|
||||||
fprintf(f, " - FPE_FLTUND");
|
fputs(" - FPE_FLTUND", f);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTRES: // floating-point inexact result
|
case FPE_FLTRES: // floating-point inexact result
|
||||||
fprintf(f, " - FPE_FLTRES");
|
fputs(" - FPE_FLTRES", f);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTINV: // floating-point invalid operation
|
case FPE_FLTINV: // floating-point invalid operation
|
||||||
fprintf(f, " - FPE_FLTINV");
|
fputs(" - FPE_FLTINV", f);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTSUB: // subscript out of range
|
case FPE_FLTSUB: // subscript out of range
|
||||||
fprintf(f, " - FPE_FLTSUB");
|
fputs(" - FPE_FLTSUB", f);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -370,28 +388,28 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
|
||||||
case SIGILL:
|
case SIGILL:
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case ILL_ILLOPC: // illegal opcode
|
case ILL_ILLOPC: // illegal opcode
|
||||||
fprintf(f, " - ILL_ILLOPC");
|
fputs(" - ILL_ILLOPC", f);
|
||||||
break;
|
break;
|
||||||
case ILL_ILLOPN: // illegal operand
|
case ILL_ILLOPN: // illegal operand
|
||||||
fprintf(f, " - ILL_ILLOPN");
|
fputs(" - ILL_ILLOPN", f);
|
||||||
break;
|
break;
|
||||||
case ILL_ILLADR: // illegal addressing mode
|
case ILL_ILLADR: // illegal addressing mode
|
||||||
fprintf(f, " - ILL_ILLADR");
|
fputs(" - ILL_ILLADR", f);
|
||||||
break;
|
break;
|
||||||
case ILL_ILLTRP: // illegal trap
|
case ILL_ILLTRP: // illegal trap
|
||||||
fprintf(f, " - ILL_ILLTRP");
|
fputs(" - ILL_ILLTRP", f);
|
||||||
break;
|
break;
|
||||||
case ILL_PRVOPC: // privileged opcode
|
case ILL_PRVOPC: // privileged opcode
|
||||||
fprintf(f, " - ILL_PRVOPC");
|
fputs(" - ILL_PRVOPC", f);
|
||||||
break;
|
break;
|
||||||
case ILL_PRVREG: // privileged register
|
case ILL_PRVREG: // privileged register
|
||||||
fprintf(f, " - ILL_PRVREG");
|
fputs(" - ILL_PRVREG", f);
|
||||||
break;
|
break;
|
||||||
case ILL_COPROC: // coprocessor error
|
case ILL_COPROC: // coprocessor error
|
||||||
fprintf(f, " - ILL_COPROC");
|
fputs(" - ILL_COPROC", f);
|
||||||
break;
|
break;
|
||||||
case ILL_BADSTK: // internal stack error
|
case ILL_BADSTK: // internal stack error
|
||||||
fprintf(f, " - ILL_BADSTK");
|
fputs(" - ILL_BADSTK", f);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -401,20 +419,22 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
|
||||||
break;
|
break;
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
bPrintCallstack=false;
|
bPrintCallstack=false;
|
||||||
fprintf(f, ".\n");
|
fputs(".\n", f);
|
||||||
break;
|
break;
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case SEGV_MAPERR: // address not mapped to object
|
case SEGV_MAPERR: // address not mapped to object
|
||||||
fprintf(f, " - SEGV_MAPERR");
|
fputs(" - SEGV_MAPERR", f);
|
||||||
break;
|
break;
|
||||||
case SEGV_ACCERR: // invalid permissions for mapped object
|
case SEGV_ACCERR: // invalid permissions for mapped object
|
||||||
fprintf(f, " - SEGV_ACCERR");
|
fputs(" - SEGV_ACCERR", f);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(f, " (at 0x%p).\n",
|
fprintf(f, " (%sat 0x%p).\n",
|
||||||
|
(type==-1)? "" :
|
||||||
|
(type==0) ? "reading " : "writing ",
|
||||||
info->si_addr);
|
info->si_addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -425,7 +445,10 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
|
||||||
print_stacktrace(f, true);
|
print_stacktrace(f, true);
|
||||||
fputs("\nPlease report this to the cppcheck developers!\n", f);
|
fputs("\nPlease report this to the cppcheck developers!\n", f);
|
||||||
}
|
}
|
||||||
abort();
|
|
||||||
|
// now let the system proceed, shutdown and hopefully dump core for post-mortem analysis
|
||||||
|
signal(signo, SIG_DFL);
|
||||||
|
kill(killid, signo);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue