Display backtrace when a program segfaults
When an application crashes, with a segfault for example it can be usefull have debugging help like a stacktrace of function calls.
This can be achieved by trapping the SIGSEGV
unix signal and by using the
backtrace(3)
and backtrace_symbols(3)
GNU extensions functions.
Intercept SIGSEGV signal (and others)
This is done via the traditional use of sigaction
:
#include <signal.h>
struct sigaction handler;
sigemptyset(&handler.sa_mask);
handler.sa_flags = SA_NODEFER | SA_RESETHAND;
handler.sa_handler = sigsegv_handler;
sigaction(SIGSEGV, &handler, NULL);
sigaction(SIGBUS, &handler, NULL);
sigaction(SIGFPE, &handler, NULL);
sigaction(SIGKILL, &handler, NULL);
Display backtrace of functions calls
Next, implement the sigsegv_handler
function to display the stacktrace:
#define BACKTRACE_SIZE 100
void sigsegv_handler(int sig) {
struct sigaction act;
int nptrs, i;
void *buffer[BACKTRACE_SIZE];
char **strings;
fprintf(stderr, "This program crashed with signal %d\n", sig);
fprintf(stderr, "-- STACK TRACE START\n");
nptrs = backtrace(buffer, BACKTRACE_SIZE);
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
return;
}
for (i = 0; i < nptrs; ++i) {
fprintf("%d\t%s\n", i, strings[i]);
}
free(strings);
fprintf(stderr, "-- STACK TRACE END\n");
/* Restore the default behavior for the traped signal */
sigemptyset(&act.sa_mask);
act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
act.sa_handler = SIG_DFL;
sigaction(sig, &act, NULL);
kill(getpid(), sig);
}