diff options
author | Ned Bass <[email protected]> | 2014-10-10 18:05:54 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2014-10-13 10:39:39 -0700 |
commit | e82cdc3acc4afe52c3ddc3fe9e4f456fdef80f41 (patch) | |
tree | d004814272246ef12eeeb07b9f5721da1602f621 /cmd | |
parent | bf2850de82af89b6d56fbbe9ee99bd9f09c628dc (diff) |
ztest: print backtrace on SIGSEGV and SIGABRT
Add signal handlers to print a backtrace if we crash or assert.
Signed-off-by: Ned Bass <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #2788
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/ztest/ztest.c | 44 |
1 files changed, 44 insertions, 0 deletions
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 <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); |