ztest: print backtrace on SIGSEGV and SIGABRT

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
This commit is contained in:
Ned Bass 2014-10-10 18:05:54 -07:00 committed by Brian Behlendorf
parent bf2850de82
commit e82cdc3acc
1 changed files with 44 additions and 0 deletions

View File

@ -124,6 +124,9 @@
#include <math.h> #include <math.h>
#include <sys/fs/zfs.h> #include <sys/fs/zfs.h>
#include <libnvpair.h> #include <libnvpair.h>
#ifdef __GNUC__
#include <execinfo.h> /* for backtrace() */
#endif
static int ztest_fd_data = -1; static int ztest_fd_data = -1;
static int ztest_fd_rand = -1; static int ztest_fd_rand = -1;
@ -481,6 +484,30 @@ _umem_logging_init(void)
return ("fail,contents"); /* $UMEM_LOGGING setting */ 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 #define FATAL_MSG_SZ 1024
char *fatal_msg; char *fatal_msg;
@ -6264,11 +6291,28 @@ main(int argc, char **argv)
boolean_t hasalt; boolean_t hasalt;
int f; int f;
char *fd_data_str = getenv("ZTEST_FD_DATA"); char *fd_data_str = getenv("ZTEST_FD_DATA");
struct sigaction action;
(void) setvbuf(stdout, NULL, _IOLBF, 0); (void) setvbuf(stdout, NULL, _IOLBF, 0);
dprintf_setup(&argc, argv); 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); ztest_fd_rand = open("/dev/urandom", O_RDONLY);
ASSERT3S(ztest_fd_rand, >=, 0); ASSERT3S(ztest_fd_rand, >=, 0);