Fix possible segmentation fault in un*x signal handler. Use SIGUSR1 for debugging purposes

This commit is contained in:
Alexander Mai 2015-09-29 12:56:13 +02:00
parent e6467703b2
commit ba2671e19a
1 changed files with 36 additions and 15 deletions

View File

@ -214,6 +214,7 @@ static const Signaltype listofsignals[] = {
DECLARE_SIGNAL(SIGINT), DECLARE_SIGNAL(SIGINT),
DECLARE_SIGNAL(SIGSEGV), DECLARE_SIGNAL(SIGSEGV),
// don't care: SIGTERM // don't care: SIGTERM
DECLARE_SIGNAL(SIGUSR1)
}; };
/* /*
@ -239,24 +240,24 @@ static void print_stacktrace(FILE* f, bool demangling, int maxdepth)
// 32 vs. 64bit // 32 vs. 64bit
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8) #define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
void *array[32]= {0}; // the less resources the better... void *array[32]= {0}; // the less resources the better...
const int depth = backtrace(array, (int)GetArrayLength(array)); const int currentdepth = backtrace(array, (int)GetArrayLength(array));
const int offset=3; // the first two entries are simply within our own exception handling code, third is within libc const int offset=2; // some entries on top are within our own exception handling code or libc
if (maxdepth<0) if (maxdepth<0)
maxdepth=depth+offset; maxdepth=currentdepth-offset;
else else
maxdepth+=offset; maxdepth = std::min(maxdepth, currentdepth);
char **symbolstrings = backtrace_symbols(array, depth); char **symbolstrings = backtrace_symbols(array, currentdepth);
if (symbolstrings) { if (symbolstrings) {
fputs("Callstack:\n", f); fputs("Callstack:\n", f);
for (int i = offset; i < maxdepth; ++i) { for (int i = offset; i < maxdepth; ++i) {
const char * const symbol = symbolstrings[i]; const char * const symbol = symbolstrings[i];
char * realname = nullptr; char * realname = nullptr;
const char * const firstBracketName = strchr(symbol, '('); const char * const firstBracketName = strchr(symbol, '(');
const char * const firstBracketAddress = strchr(symbol, '['); const char * const firstBracketAddress = strchr(symbol, '[');
const char * const secondBracketAddress = strchr(firstBracketAddress, ']'); const char * const secondBracketAddress = strchr(firstBracketAddress, ']');
const char * const beginAddress = firstBracketAddress+3; const char * const beginAddress = firstBracketAddress+3;
const int addressLen = int(secondBracketAddress-beginAddress); const int addressLen = int(secondBracketAddress-beginAddress);
const int padLen = int(ADDRESSDISPLAYLENGTH-addressLen); const int padLen = int(ADDRESSDISPLAYLENGTH-addressLen);
if (demangling && firstBracketName) { if (demangling && firstBracketName) {
const char * const plus = strchr(firstBracketName, '+'); const char * const plus = strchr(firstBracketName, '+');
if (plus && (plus>(firstBracketName+1))) { if (plus && (plus>(firstBracketName+1))) {
@ -292,9 +293,9 @@ static void print_stacktrace(FILE* f, bool demangling, int maxdepth)
#endif #endif
} }
static const size_t MYSTACKSIZE = 16*1024+SIGSTKSZ; static const size_t MYSTACKSIZE = 16*1024+SIGSTKSZ; // wild guess about a reasonable buffer
static char mytstack[MYSTACKSIZE]; // alternative stack for signal handler static char mytstack[MYSTACKSIZE]; // alternative stack for signal handler
static bool bStackBelowHeap=false; static bool bStackBelowHeap=false; // lame attempt to locate heap vs. stack address space
/* /*
* \return true if address is supposed to be on stack (contrary to heap or elsewhere). If ptr is 0 false will be returned. * \return true if address is supposed to be on stack (contrary to heap or elsewhere). If ptr is 0 false will be returned.
@ -330,12 +331,13 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
#endif #endif
const char * const signame = signal_name(signo); const char * const signame = signal_name(signo);
bool bPrintCallstack=true; bool bPrintCallstack=true;
bool bUnexpectedSignal=true;
const bool isaddressonstack = isAddressOnStack(info->si_addr); const bool isaddressonstack = isAddressOnStack(info->si_addr);
FILE* f = (CppCheckExecutor::getExceptionOutput()=="stderr") ? stderr : stdout; FILE* f = (CppCheckExecutor::getExceptionOutput()=="stderr") ? stderr : stdout;
fputs("Internal error: cppcheck received signal ", f);
fputs(signame, f);
switch (signo) { switch (signo) {
case SIGBUS: case SIGBUS:
fputs("Internal error: cppcheck received signal ", f);
fputs(signame, f);
switch (info->si_code) { switch (info->si_code) {
case BUS_ADRALN: // invalid address alignment case BUS_ADRALN: // invalid address alignment
fputs(" - BUS_ADRALN", f); fputs(" - BUS_ADRALN", f);
@ -363,6 +365,8 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
(unsigned long)info->si_addr); (unsigned long)info->si_addr);
break; break;
case SIGFPE: case SIGFPE:
fputs("Internal error: cppcheck received signal ", f);
fputs(signame, f);
switch (info->si_code) { switch (info->si_code) {
case FPE_INTDIV: // integer divide by zero case FPE_INTDIV: // integer divide by zero
fputs(" - FPE_INTDIV", f); fputs(" - FPE_INTDIV", f);
@ -395,6 +399,8 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
(unsigned long)info->si_addr); (unsigned long)info->si_addr);
break; break;
case SIGILL: case SIGILL:
fputs("Internal error: cppcheck received signal ", f);
fputs(signame, f);
switch (info->si_code) { switch (info->si_code) {
case ILL_ILLOPC: // illegal opcode case ILL_ILLOPC: // illegal opcode
fputs(" - ILL_ILLOPC", f); fputs(" - ILL_ILLOPC", f);
@ -428,10 +434,15 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
(isaddressonstack)?" Stackoverflow?":""); (isaddressonstack)?" Stackoverflow?":"");
break; break;
case SIGINT: case SIGINT:
bUnexpectedSignal=false;
fputs("cppcheck received signal ", f);
fputs(signame, f);
bPrintCallstack=false; bPrintCallstack=false;
fputs(".\n", f); fputs(".\n", f);
break; break;
case SIGSEGV: case SIGSEGV:
fputs("Internal error: cppcheck received signal ", f);
fputs(signame, f);
switch (info->si_code) { switch (info->si_code) {
case SEGV_MAPERR: // address not mapped to object case SEGV_MAPERR: // address not mapped to object
fputs(" - SEGV_MAPERR", f); fputs(" - SEGV_MAPERR", f);
@ -449,17 +460,27 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
(isaddressonstack)?" Stackoverflow?":"" (isaddressonstack)?" Stackoverflow?":""
); );
break; break;
case SIGUSR1:
bUnexpectedSignal=false;
fputs("cppcheck received signal ", f);
fputs(signame, f);
fputs(".\n", f);
break;
default: default:
fputs("Internal error: cppcheck received signal ", f);
fputs(signame, f);
fputs(".\n", f); fputs(".\n", f);
break; break;
} }
if (bPrintCallstack) { if (bPrintCallstack) {
print_stacktrace(f, true, -1 /*(isaddressonstack)?8:-1*/); print_stacktrace(f, true, -1);
}
if (bUnexpectedSignal) {
fputs("\nPlease report this to the cppcheck developers!\n", f); fputs("\nPlease report this to the cppcheck developers!\n", f);
} }
fflush(f); fflush(f);
// now let the system proceed, shutdown and hopefully dump core for post-mortem analysis // now let things proceed, shutdown and hopefully dump core for post-mortem analysis
signal(signo, SIG_DFL); signal(signo, SIG_DFL);
kill(killid, signo); kill(killid, signo);
} }