Display backtrace when a program segfaults

Published 12-03-2012 00:00:00

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);
}

Links