|
85 | 85 | #include <sys/brt_impl.h>
|
86 | 86 | #include <zfs_comutil.h>
|
87 | 87 | #include <sys/zstd/zstd.h>
|
| 88 | +#if (__GLIBC__ && !__UCLIBC__) |
| 89 | +#include <execinfo.h> /* for backtrace() */ |
| 90 | +#endif |
88 | 91 |
|
89 | 92 | #include <libnvpair.h>
|
90 | 93 | #include <libzutil.h>
|
@@ -829,11 +832,41 @@ usage(void)
|
829 | 832 | static void
|
830 | 833 | dump_debug_buffer(void)
|
831 | 834 | {
|
832 |
| - if (dump_opt['G']) { |
833 |
| - (void) printf("\n"); |
834 |
| - (void) fflush(stdout); |
835 |
| - zfs_dbgmsg_print("zdb"); |
836 |
| - } |
| 835 | + ssize_t ret __attribute__((unused)); |
| 836 | + |
| 837 | + if (!dump_opt['G']) |
| 838 | + return; |
| 839 | + /* |
| 840 | + * We use write() instead of printf() so that this function |
| 841 | + * is safe to call from a signal handler. |
| 842 | + */ |
| 843 | + ret = write(STDOUT_FILENO, "\n", 1); |
| 844 | + zfs_dbgmsg_print("zdb"); |
| 845 | +} |
| 846 | + |
| 847 | +#define BACKTRACE_SZ 100 |
| 848 | + |
| 849 | +static void sig_handler(int signo) |
| 850 | +{ |
| 851 | + struct sigaction action; |
| 852 | +#if (__GLIBC__ && !__UCLIBC__) /* backtrace() is a GNU extension */ |
| 853 | + int nptrs; |
| 854 | + void *buffer[BACKTRACE_SZ]; |
| 855 | + |
| 856 | + nptrs = backtrace(buffer, BACKTRACE_SZ); |
| 857 | + backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO); |
| 858 | +#endif |
| 859 | + dump_debug_buffer(); |
| 860 | + |
| 861 | + /* |
| 862 | + * Restore default action and re-raise signal so SIGSEGV and |
| 863 | + * SIGABRT can trigger a core dump. |
| 864 | + */ |
| 865 | + action.sa_handler = SIG_DFL; |
| 866 | + sigemptyset(&action.sa_mask); |
| 867 | + action.sa_flags = 0; |
| 868 | + (void) sigaction(signo, &action, NULL); |
| 869 | + raise(signo); |
837 | 870 | }
|
838 | 871 |
|
839 | 872 | /*
|
@@ -8905,9 +8938,27 @@ main(int argc, char **argv)
|
8905 | 8938 | char *spa_config_path_env, *objset_str;
|
8906 | 8939 | boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE;
|
8907 | 8940 | nvlist_t *cfg = NULL;
|
| 8941 | + struct sigaction action; |
8908 | 8942 |
|
8909 | 8943 | dprintf_setup(&argc, argv);
|
8910 | 8944 |
|
| 8945 | + /* |
| 8946 | + * Set up signal handlers, so if we crash due to bad on-disk data we |
| 8947 | + * can get more info. Unlike ztest, we don't bail out if we can't set |
| 8948 | + * up signal handlers, because zdb is very useful without them. |
| 8949 | + */ |
| 8950 | + action.sa_handler = sig_handler; |
| 8951 | + sigemptyset(&action.sa_mask); |
| 8952 | + action.sa_flags = 0; |
| 8953 | + if (sigaction(SIGSEGV, &action, NULL) < 0) { |
| 8954 | + (void) fprintf(stderr, "zdb: cannot catch SIGSEGV: %s\n", |
| 8955 | + strerror(errno)); |
| 8956 | + } |
| 8957 | + if (sigaction(SIGABRT, &action, NULL) < 0) { |
| 8958 | + (void) fprintf(stderr, "zdb: cannot catch SIGABRT: %s\n", |
| 8959 | + strerror(errno)); |
| 8960 | + } |
| 8961 | + |
8911 | 8962 | /*
|
8912 | 8963 | * If there is an environment variable SPA_CONFIG_PATH it overrides
|
8913 | 8964 | * default spa_config_path setting. If -U flag is specified it will
|
|
0 commit comments