Linux crashlog: Use sigaction to get more info on fatal signals.

This commit is contained in:
Jonathan G Rennison
2016-06-10 19:29:43 +01:00
parent 2a2ff30c3f
commit abbc960e96
3 changed files with 116 additions and 4 deletions

View File

@@ -78,6 +78,9 @@ static void LogStacktraceSigSegvHandler(int sig)
class CrashLogUnix : public CrashLog {
/** Signal that has been thrown. */
int signum;
#ifdef WITH_SIGACTION
siginfo_t *si;
#endif
/* virtual */ char *LogOSVersion(char *buffer, const char *last) const
{
@@ -101,14 +104,29 @@ class CrashLogUnix : public CrashLog {
/* virtual */ char *LogError(char *buffer, const char *last, const char *message) const
{
return buffer + seprintf(buffer, last,
buffer += seprintf(buffer, last,
"Crash reason:\n"
" Signal: %s (%d)\n"
" Message: %s\n\n",
" Signal: %s (%d)\n",
strsignal(this->signum),
this->signum,
this->signum);
#ifdef WITH_SIGACTION
if (this->si) {
buffer += seprintf(buffer, last,
" si_code: %d\n",
this->si->si_code);
if (this->signum != SIGABRT) {
buffer += seprintf(buffer, last,
" fault address: %p\n",
this->si->si_addr);
}
}
#endif
buffer += seprintf(buffer, last,
" Message: %s\n\n",
message == NULL ? "<none>" : message
);
return buffer;
}
#if defined(SUNOS)
@@ -378,10 +396,17 @@ public:
* A crash log is always generated by signal.
* @param signum the signal that was caused by the crash.
*/
#ifdef WITH_SIGACTION
CrashLogUnix(int signum, siginfo_t *si) :
signum(signum), si(si)
{
}
#else
CrashLogUnix(int signum) :
signum(signum)
{
}
#endif
};
/** The signals we want our crash handler to handle. */
@@ -392,7 +417,11 @@ static const int _signals_to_handle[] = { SIGSEGV, SIGABRT, SIGFPE, SIGBUS, SIGI
* @note Not static so it shows up in the backtrace.
* @param signum the signal that caused us to crash.
*/
#ifdef WITH_SIGACTION
static void CDECL HandleCrash(int signum, siginfo_t *si, void *context)
#else
static void CDECL HandleCrash(int signum)
#endif
{
/* Disable all handling of signals by us, so we don't go into infinite loops. */
for (const int *i = _signals_to_handle; i != endof(_signals_to_handle); i++) {
@@ -412,7 +441,11 @@ static void CDECL HandleCrash(int signum)
abort();
}
#ifdef WITH_SIGACTION
CrashLogUnix log(signum, si);
#else
CrashLogUnix log(signum);
#endif
log.MakeCrashLog();
CrashLog::AfterCrashLogCleanup();
@@ -422,6 +455,15 @@ static void CDECL HandleCrash(int signum)
/* static */ void CrashLog::InitialiseCrashLog()
{
for (const int *i = _signals_to_handle; i != endof(_signals_to_handle); i++) {
#ifdef WITH_SIGACTION
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO | SA_RESTART;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = HandleCrash;
sigaction(*i, &sa, NULL);
#else
signal(*i, HandleCrash);
#endif
}
}