#define _GNU_SOURCE
#include <stdlib.h>
+#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <setjmp.h>
#include <time.h>
#include <unistd.h>
#include <sys/syscall.h>
+#include <execinfo.h>
#include "sig-monitor.h"
#include "verbose.h"
static _Thread_local int thread_timer_set;
static _Thread_local timer_t thread_timerid;
+/*
+ * Dumps the current stack
+ */
+static void dumpstack(int crop, int signum)
+{
+ int idx, count, rc;
+ void *addresses[100];
+ char **locations;
+ char buffer[8000];
+ size_t pos, length;
+
+ count = backtrace(addresses, sizeof addresses / sizeof *addresses);
+ if (count <= crop)
+ crop = 0;
+ count -= crop;
+ locations = backtrace_symbols(&addresses[crop], count);
+ if (locations == NULL)
+ ERROR("can't get the backtrace (returned %d addresses)", count);
+ else {
+ length = sizeof buffer - 1;
+ pos = 0;
+ idx = 0;
+ while (pos < length && idx < count) {
+ rc = snprintf(&buffer[pos], length - pos, " [%d/%d] %s\n", idx + 1, count, locations[idx]);
+ pos += rc >= 0 ? rc : 0;
+ idx++;
+ }
+ buffer[length] = 0;
+ if (signum)
+ ERROR("BACKTRACE due to signal %s/%d:\n%s", strsignal(signum), signum, buffer);
+ else
+ ERROR("BACKTRACE:\n%s", buffer);
+ free(locations);
+ }
+}
+
/*
* Creates a timer for the current thread
*
static void on_signal_terminate (int signum)
{
ERROR("Terminating signal %d received: %s", signum, strsignal(signum));
+ if (signum == SIGABRT)
+ dumpstack(3, signum);
exit(1);
}
sigset_t sigset;
ERROR("ALERT! signal %d received: %s", signum, strsignal(signum));
+ if (error_handler == NULL && signum == SIG_FOR_TIMER)
+ return;
+
+ dumpstack(3, signum);
// unlock signal to allow a new signal to come
if (error_handler != NULL) {
sigprocmask(SIG_UNBLOCK, &sigset, 0);
longjmp(*error_handler, signum);
}
- if (signum == SIG_FOR_TIMER)
- return;
ERROR("Unmonitored signal %d received: %s", signum, strsignal(signum));
exit(2);
}
int sig_monitor_init()
{
- static int sigerr[] = { SIG_FOR_TIMER, SIGSEGV, SIGFPE, 0 };
- static int sigterm[] = { SIGINT, SIGABRT, 0 };
+ static int sigerr[] = { SIG_FOR_TIMER, SIGSEGV, SIGFPE, SIGILL, SIGBUS, 0 };
+ static int sigterm[] = { SIGINT, SIGABRT, SIGTERM, 0 };
return (install(on_signal_error, sigerr) & install(on_signal_terminate, sigterm)) - 1;
}
}
-
-
-