Signal handling: Don't mix sigaction and signal. SIGUSR1 can be used to print current callstack, SIGUSR2 is being ignored. Minor refactoring
This commit is contained in:
parent
0967700f4b
commit
9da28d5f4c
|
@ -211,8 +211,9 @@ std::size_t GetArrayLength(const T(&)[size])
|
||||||
#if defined(USE_UNIX_SIGNAL_HANDLING)
|
#if defined(USE_UNIX_SIGNAL_HANDLING)
|
||||||
/*
|
/*
|
||||||
* Try to print the callstack.
|
* Try to print the callstack.
|
||||||
* That is very sensitive to the operating system, hardware, compiler and runtime!
|
* That is very sensitive to the operating system, hardware, compiler and runtime.
|
||||||
* The code is not meant for production environment, it's using functions not whitelisted for usage in a signal handler function.
|
* The code is not meant for production environment!
|
||||||
|
* One reason is named first: it's using functions not whitelisted for usage in a signal handler function.
|
||||||
*/
|
*/
|
||||||
static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool lowMem)
|
static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool lowMem)
|
||||||
{
|
{
|
||||||
|
@ -220,8 +221,8 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
||||||
// 32 vs. 64bit
|
// 32 vs. 64bit
|
||||||
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
|
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
|
||||||
const int fd = fileno(output);
|
const int fd = fileno(output);
|
||||||
void *array[32]= {0}; // the less resources the better...
|
void *callstackArray[32]= {0}; // the less resources the better...
|
||||||
const int currentdepth = backtrace(array, (int)GetArrayLength(array));
|
const int currentdepth = backtrace(callstackArray, (int)GetArrayLength(callstackArray));
|
||||||
const int offset=2; // some entries on top are within our own exception handling code or 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=currentdepth-offset;
|
maxdepth=currentdepth-offset;
|
||||||
|
@ -229,17 +230,16 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
||||||
maxdepth = std::min(maxdepth, currentdepth);
|
maxdepth = std::min(maxdepth, currentdepth);
|
||||||
if (lowMem) {
|
if (lowMem) {
|
||||||
fputs("Callstack (symbols only):\n", output);
|
fputs("Callstack (symbols only):\n", output);
|
||||||
backtrace_symbols_fd(array+offset, maxdepth, fd);
|
backtrace_symbols_fd(callstackArray+offset, maxdepth, fd);
|
||||||
fflush(output);
|
|
||||||
} else {
|
} else {
|
||||||
char **symbolstrings = backtrace_symbols(array, currentdepth);
|
char **symbolStringList = backtrace_symbols(callstackArray, currentdepth);
|
||||||
if (symbolstrings) {
|
if (symbolStringList) {
|
||||||
fputs("Callstack:\n", output);
|
fputs("Callstack:\n", output);
|
||||||
for (int i = offset; i < maxdepth; ++i) {
|
for (int i = offset; i < maxdepth; ++i) {
|
||||||
const char * const symbol = symbolstrings[i];
|
const char * const symbolString = symbolStringList[i];
|
||||||
char * realname = nullptr;
|
char * realnameString = nullptr;
|
||||||
const char * const firstBracketName = strchr(symbol, '(');
|
const char * const firstBracketName = strchr(symbolString, '(');
|
||||||
const char * const firstBracketAddress = strchr(symbol, '[');
|
const char * const firstBracketAddress = strchr(symbolString, '[');
|
||||||
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);
|
||||||
|
@ -247,12 +247,14 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
||||||
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))) {
|
||||||
char input_buffer[512]= {0};
|
char input_buffer[1024]= {0};
|
||||||
strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
|
strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
|
||||||
char output_buffer[1024]= {0};
|
char output_buffer[2048]= {0};
|
||||||
size_t length = GetArrayLength(output_buffer);
|
size_t length = GetArrayLength(output_buffer);
|
||||||
int status=0;
|
int status=0;
|
||||||
realname = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success
|
// We're violating the specification - passing stack address instead of malloc'ed heap.
|
||||||
|
// Benefit is that no further heap is required, while there is sufficient stack...
|
||||||
|
realnameString = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const int ordinal=i-offset;
|
const int ordinal=i-offset;
|
||||||
|
@ -261,17 +263,17 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
||||||
if (padLen>0)
|
if (padLen>0)
|
||||||
fprintf(output, "%0*d",
|
fprintf(output, "%0*d",
|
||||||
padLen, 0);
|
padLen, 0);
|
||||||
if (realname) {
|
if (realnameString) {
|
||||||
fprintf(output, "%.*s in %s\n",
|
fprintf(output, "%.*s in %s\n",
|
||||||
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
||||||
realname);
|
realnameString);
|
||||||
} else {
|
} else {
|
||||||
fprintf(output, "%.*s in %.*s\n",
|
fprintf(output, "%.*s in %.*s\n",
|
||||||
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
||||||
(int)(firstBracketAddress-symbol), symbol);
|
(int)(firstBracketAddress-symbolString), symbolString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(symbolstrings);
|
free(symbolStringList);
|
||||||
} else {
|
} else {
|
||||||
fputs("Callstack could not be obtained\n", output);
|
fputs("Callstack could not be obtained\n", output);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +321,7 @@ static const Signalmap_t listofsignals = make_container< Signalmap_t > ()
|
||||||
DECLARE_SIGNAL(SIGSYS)
|
DECLARE_SIGNAL(SIGSYS)
|
||||||
// don't care: SIGTERM
|
// don't care: SIGTERM
|
||||||
DECLARE_SIGNAL(SIGUSR1)
|
DECLARE_SIGNAL(SIGUSR1)
|
||||||
DECLARE_SIGNAL(SIGUSR2)
|
//DECLARE_SIGNAL(SIGUSR2) no usage currently
|
||||||
;
|
;
|
||||||
#undef DECLARE_SIGNAL
|
#undef DECLARE_SIGNAL
|
||||||
/*
|
/*
|
||||||
|
@ -342,10 +344,11 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
||||||
#endif
|
#endif
|
||||||
const Signalmap_t::const_iterator it=listofsignals.find(signo);
|
const Signalmap_t::const_iterator it=listofsignals.find(signo);
|
||||||
const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str();
|
const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str();
|
||||||
bool printCallstack=true;
|
bool printCallstack=true; // try to print a callstack?
|
||||||
bool lowMem=false;
|
bool lowMem=false; // was low-memory condition detected?
|
||||||
bool unexpectedSignal=true;
|
bool unexpectedSignal=true; // unexpected indicates things didn't go as they should...
|
||||||
const bool isaddressonstack = IsAddressOnStack(info->si_addr);
|
bool terminate=true; // exit process/thread
|
||||||
|
const bool isAddressOnStack = IsAddressOnStack(info->si_addr);
|
||||||
FILE* output = CppCheckExecutor::getExceptionOutput();
|
FILE* output = CppCheckExecutor::getExceptionOutput();
|
||||||
switch (signo) {
|
switch (signo) {
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
|
@ -450,7 +453,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
||||||
}
|
}
|
||||||
fprintf(output, " (at 0x%lx).%s\n",
|
fprintf(output, " (at 0x%lx).%s\n",
|
||||||
(unsigned long)info->si_addr,
|
(unsigned long)info->si_addr,
|
||||||
(isaddressonstack)?" Stackoverflow?":"");
|
(isAddressOnStack)?" Stackoverflow?":"");
|
||||||
break;
|
break;
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
unexpectedSignal=false; // legal usage: interrupt application via CTRL-C
|
unexpectedSignal=false; // legal usage: interrupt application via CTRL-C
|
||||||
|
@ -476,14 +479,14 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
||||||
(type==-1)? "" :
|
(type==-1)? "" :
|
||||||
(type==0) ? "reading " : "writing ",
|
(type==0) ? "reading " : "writing ",
|
||||||
(unsigned long)info->si_addr,
|
(unsigned long)info->si_addr,
|
||||||
(isaddressonstack)?" Stackoverflow?":""
|
(isAddressOnStack)?" Stackoverflow?":""
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
case SIGUSR2:
|
|
||||||
fputs("cppcheck received signal ", output);
|
fputs("cppcheck received signal ", output);
|
||||||
fputs(signame, output);
|
fputs(signame, output);
|
||||||
fputs(".\n", output);
|
fputs(".\n", output);
|
||||||
|
terminate=false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fputs("Internal error: cppcheck received signal ", output);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
|
@ -499,9 +502,14 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
||||||
}
|
}
|
||||||
fflush(output);
|
fflush(output);
|
||||||
|
|
||||||
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
|
if (terminate) {
|
||||||
signal(signo, SIG_DFL);
|
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
|
||||||
kill(killid, signo);
|
struct sigaction act;
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_handler=SIG_DFL;
|
||||||
|
sigaction(signo, &act, nullptr);
|
||||||
|
kill(killid, signo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue