From e82cdc3acc4afe52c3ddc3fe9e4f456fdef80f41 Mon Sep 17 00:00:00 2001 From: Ned Bass Date: Fri, 10 Oct 2014 18:05:54 -0700 Subject: [PATCH] ztest: print backtrace on SIGSEGV and SIGABRT Add signal handlers to print a backtrace if we crash or assert. Signed-off-by: Ned Bass Signed-off-by: Brian Behlendorf Closes #2788 --- cmd/ztest/ztest.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index a087444c8..203da4032 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -124,6 +124,9 @@ #include #include #include +#ifdef __GNUC__ +#include /* 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);