]> granicus.if.org Git - zfs/commitdiff
ztest: print backtrace on SIGSEGV and SIGABRT
authorNed Bass <bass6@llnl.gov>
Sat, 11 Oct 2014 01:05:54 +0000 (18:05 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 13 Oct 2014 17:39:39 +0000 (10:39 -0700)
Add signal handlers to print a backtrace if we crash or assert.

Signed-off-by: Ned Bass <bass6@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #2788

cmd/ztest/ztest.c

index a087444c8bda606297a2ff827e218ad3ebc06ed9..203da40320340de44029428c6a0b9c20f1ec31eb 100644 (file)
 #include <math.h>
 #include <sys/fs/zfs.h>
 #include <libnvpair.h>
+#ifdef __GNUC__
+#include <execinfo.h> /* for backtrace() */
+#endif
 
 static int ztest_fd_data = -1;
 static int ztest_fd_rand = -1;
@@ -481,6 +484,30 @@ _umem_logging_init(void)
        return ("fail,contents"); /* $UMEM_LOGGING setting */
 }
 
+#define        BACKTRACE_SZ    100
+
+static void sig_handler(int signo)
+{
+       struct sigaction action;
+#ifdef __GNUC__ /* backtrace() is a GNU extension */
+       int nptrs;
+       void *buffer[BACKTRACE_SZ];
+
+       nptrs = backtrace(buffer, BACKTRACE_SZ);
+       backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
+#endif
+
+       /*
+        * Restore default action and re-raise signal so SIGSEGV and
+        * SIGABRT can trigger a core dump.
+        */
+       action.sa_handler = SIG_DFL;
+       sigemptyset(&action.sa_mask);
+       action.sa_flags = 0;
+       (void) sigaction(signo, &action, NULL);
+       raise(signo);
+}
+
 #define        FATAL_MSG_SZ    1024
 
 char *fatal_msg;
@@ -6264,11 +6291,28 @@ main(int argc, char **argv)
        boolean_t hasalt;
        int f;
        char *fd_data_str = getenv("ZTEST_FD_DATA");
+       struct sigaction action;
 
        (void) setvbuf(stdout, NULL, _IOLBF, 0);
 
        dprintf_setup(&argc, argv);
 
+       action.sa_handler = sig_handler;
+       sigemptyset(&action.sa_mask);
+       action.sa_flags = 0;
+
+       if (sigaction(SIGSEGV, &action, NULL) < 0) {
+               (void) fprintf(stderr, "ztest: cannot catch SIGSEGV: %s.\n",
+                   strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       if (sigaction(SIGABRT, &action, NULL) < 0) {
+               (void) fprintf(stderr, "ztest: cannot catch SIGABRT: %s.\n",
+                   strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
        ztest_fd_rand = open("/dev/urandom", O_RDONLY);
        ASSERT3S(ztest_fd_rand, >=, 0);