|
84 | 84 | #include <sys/brt_impl.h>
|
85 | 85 | #include <zfs_comutil.h>
|
86 | 86 | #include <sys/zstd/zstd.h>
|
| 87 | +#if (__GLIBC__ && !__UCLIBC__) |
| 88 | +#include <execinfo.h> /* for backtrace() */ |
| 89 | +#endif |
87 | 90 |
|
88 | 91 | #include <libnvpair.h>
|
89 | 92 | #include <libzutil.h>
|
@@ -926,11 +929,41 @@ usage(void)
|
926 | 929 | static void
|
927 | 930 | dump_debug_buffer(void)
|
928 | 931 | {
|
929 |
| - if (dump_opt['G']) { |
930 |
| - (void) printf("\n"); |
931 |
| - (void) fflush(stdout); |
932 |
| - zfs_dbgmsg_print("zdb"); |
933 |
| - } |
| 932 | + ssize_t ret __attribute__((unused)); |
| 933 | + |
| 934 | + if (!dump_opt['G']) |
| 935 | + return; |
| 936 | + /* |
| 937 | + * We use write() instead of printf() so that this function |
| 938 | + * is safe to call from a signal handler. |
| 939 | + */ |
| 940 | + ret = write(STDOUT_FILENO, "\n", 1); |
| 941 | + zfs_dbgmsg_print("zdb"); |
| 942 | +} |
| 943 | + |
| 944 | +#define BACKTRACE_SZ 100 |
| 945 | + |
| 946 | +static void sig_handler(int signo) |
| 947 | +{ |
| 948 | + struct sigaction action; |
| 949 | +#if (__GLIBC__ && !__UCLIBC__) /* backtrace() is a GNU extension */ |
| 950 | + int nptrs; |
| 951 | + void *buffer[BACKTRACE_SZ]; |
| 952 | + |
| 953 | + nptrs = backtrace(buffer, BACKTRACE_SZ); |
| 954 | + backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO); |
| 955 | +#endif |
| 956 | + dump_debug_buffer(); |
| 957 | + |
| 958 | + /* |
| 959 | + * Restore default action and re-raise signal so SIGSEGV and |
| 960 | + * SIGABRT can trigger a core dump. |
| 961 | + */ |
| 962 | + action.sa_handler = SIG_DFL; |
| 963 | + sigemptyset(&action.sa_mask); |
| 964 | + action.sa_flags = 0; |
| 965 | + (void) sigaction(signo, &action, NULL); |
| 966 | + raise(signo); |
934 | 967 | }
|
935 | 968 |
|
936 | 969 | /*
|
@@ -8934,9 +8967,27 @@ main(int argc, char **argv)
|
8934 | 8967 | char *spa_config_path_env, *objset_str;
|
8935 | 8968 | boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE;
|
8936 | 8969 | nvlist_t *cfg = NULL;
|
| 8970 | + struct sigaction action; |
8937 | 8971 |
|
8938 | 8972 | dprintf_setup(&argc, argv);
|
8939 | 8973 |
|
| 8974 | + /* |
| 8975 | + * Set up signal handlers, so if we crash due to bad on-disk data we |
| 8976 | + * can get more info. Unlike ztest, we don't bail out if we can't set |
| 8977 | + * up signal handlers, because zdb is very useful without them. |
| 8978 | + */ |
| 8979 | + action.sa_handler = sig_handler; |
| 8980 | + sigemptyset(&action.sa_mask); |
| 8981 | + action.sa_flags = 0; |
| 8982 | + if (sigaction(SIGSEGV, &action, NULL) < 0) { |
| 8983 | + (void) fprintf(stderr, "zdb: cannot catch SIGSEGV: %s\n", |
| 8984 | + strerror(errno)); |
| 8985 | + } |
| 8986 | + if (sigaction(SIGABRT, &action, NULL) < 0) { |
| 8987 | + (void) fprintf(stderr, "zdb: cannot catch SIGABRT: %s\n", |
| 8988 | + strerror(errno)); |
| 8989 | + } |
| 8990 | + |
8940 | 8991 | /*
|
8941 | 8992 | * If there is an environment variable SPA_CONFIG_PATH it overrides
|
8942 | 8993 | * default spa_config_path setting. If -U flag is specified it will
|
|
0 commit comments