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)
|
||||
/*
|
||||
* Try to print the callstack.
|
||||
* 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.
|
||||
* That is very sensitive to the operating system, hardware, compiler and runtime.
|
||||
* 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)
|
||||
{
|
||||
|
@ -220,8 +221,8 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
|||
// 32 vs. 64bit
|
||||
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
|
||||
const int fd = fileno(output);
|
||||
void *array[32]= {0}; // the less resources the better...
|
||||
const int currentdepth = backtrace(array, (int)GetArrayLength(array));
|
||||
void *callstackArray[32]= {0}; // the less resources the better...
|
||||
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
|
||||
if (maxdepth<0)
|
||||
maxdepth=currentdepth-offset;
|
||||
|
@ -229,17 +230,16 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
|||
maxdepth = std::min(maxdepth, currentdepth);
|
||||
if (lowMem) {
|
||||
fputs("Callstack (symbols only):\n", output);
|
||||
backtrace_symbols_fd(array+offset, maxdepth, fd);
|
||||
fflush(output);
|
||||
backtrace_symbols_fd(callstackArray+offset, maxdepth, fd);
|
||||
} else {
|
||||
char **symbolstrings = backtrace_symbols(array, currentdepth);
|
||||
if (symbolstrings) {
|
||||
char **symbolStringList = backtrace_symbols(callstackArray, currentdepth);
|
||||
if (symbolStringList) {
|
||||
fputs("Callstack:\n", output);
|
||||
for (int i = offset; i < maxdepth; ++i) {
|
||||
const char * const symbol = symbolstrings[i];
|
||||
char * realname = nullptr;
|
||||
const char * const firstBracketName = strchr(symbol, '(');
|
||||
const char * const firstBracketAddress = strchr(symbol, '[');
|
||||
const char * const symbolString = symbolStringList[i];
|
||||
char * realnameString = nullptr;
|
||||
const char * const firstBracketName = strchr(symbolString, '(');
|
||||
const char * const firstBracketAddress = strchr(symbolString, '[');
|
||||
const char * const secondBracketAddress = strchr(firstBracketAddress, ']');
|
||||
const char * const beginAddress = firstBracketAddress+3;
|
||||
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) {
|
||||
const char * const plus = strchr(firstBracketName, '+');
|
||||
if (plus && (plus>(firstBracketName+1))) {
|
||||
char input_buffer[512]= {0};
|
||||
char input_buffer[1024]= {0};
|
||||
strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
|
||||
char output_buffer[1024]= {0};
|
||||
char output_buffer[2048]= {0};
|
||||
size_t length = GetArrayLength(output_buffer);
|
||||
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;
|
||||
|
@ -261,17 +263,17 @@ static void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool l
|
|||
if (padLen>0)
|
||||
fprintf(output, "%0*d",
|
||||
padLen, 0);
|
||||
if (realname) {
|
||||
if (realnameString) {
|
||||
fprintf(output, "%.*s in %s\n",
|
||||
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
||||
realname);
|
||||
realnameString);
|
||||
} else {
|
||||
fprintf(output, "%.*s in %.*s\n",
|
||||
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
||||
(int)(firstBracketAddress-symbol), symbol);
|
||||
(int)(firstBracketAddress-symbolString), symbolString);
|
||||
}
|
||||
}
|
||||
free(symbolstrings);
|
||||
free(symbolStringList);
|
||||
} else {
|
||||
fputs("Callstack could not be obtained\n", output);
|
||||
}
|
||||
|
@ -319,7 +321,7 @@ static const Signalmap_t listofsignals = make_container< Signalmap_t > ()
|
|||
DECLARE_SIGNAL(SIGSYS)
|
||||
// don't care: SIGTERM
|
||||
DECLARE_SIGNAL(SIGUSR1)
|
||||
DECLARE_SIGNAL(SIGUSR2)
|
||||
//DECLARE_SIGNAL(SIGUSR2) no usage currently
|
||||
;
|
||||
#undef DECLARE_SIGNAL
|
||||
/*
|
||||
|
@ -342,10 +344,11 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
|||
#endif
|
||||
const Signalmap_t::const_iterator it=listofsignals.find(signo);
|
||||
const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str();
|
||||
bool printCallstack=true;
|
||||
bool lowMem=false;
|
||||
bool unexpectedSignal=true;
|
||||
const bool isaddressonstack = IsAddressOnStack(info->si_addr);
|
||||
bool printCallstack=true; // try to print a callstack?
|
||||
bool lowMem=false; // was low-memory condition detected?
|
||||
bool unexpectedSignal=true; // unexpected indicates things didn't go as they should...
|
||||
bool terminate=true; // exit process/thread
|
||||
const bool isAddressOnStack = IsAddressOnStack(info->si_addr);
|
||||
FILE* output = CppCheckExecutor::getExceptionOutput();
|
||||
switch (signo) {
|
||||
case SIGABRT:
|
||||
|
@ -450,7 +453,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
|||
}
|
||||
fprintf(output, " (at 0x%lx).%s\n",
|
||||
(unsigned long)info->si_addr,
|
||||
(isaddressonstack)?" Stackoverflow?":"");
|
||||
(isAddressOnStack)?" Stackoverflow?":"");
|
||||
break;
|
||||
case SIGINT:
|
||||
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==0) ? "reading " : "writing ",
|
||||
(unsigned long)info->si_addr,
|
||||
(isaddressonstack)?" Stackoverflow?":""
|
||||
(isAddressOnStack)?" Stackoverflow?":""
|
||||
);
|
||||
break;
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
fputs("cppcheck received signal ", output);
|
||||
fputs(signame, output);
|
||||
fputs(".\n", output);
|
||||
terminate=false;
|
||||
break;
|
||||
default:
|
||||
fputs("Internal error: cppcheck received signal ", output);
|
||||
|
@ -499,9 +502,14 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
|||
}
|
||||
fflush(output);
|
||||
|
||||
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
|
||||
signal(signo, SIG_DFL);
|
||||
kill(killid, signo);
|
||||
if (terminate) {
|
||||
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler=SIG_DFL;
|
||||
sigaction(signo, &act, nullptr);
|
||||
kill(killid, signo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue