summaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorNed Bass <[email protected]>2014-10-10 18:05:54 -0700
committerBrian Behlendorf <[email protected]>2014-10-13 10:39:39 -0700
commite82cdc3acc4afe52c3ddc3fe9e4f456fdef80f41 (patch)
treed004814272246ef12eeeb07b9f5721da1602f621 /cmd
parentbf2850de82af89b6d56fbbe9ee99bd9f09c628dc (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.c44
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);