Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zdb/ztest: improve and harmonise crash output #16181

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 47 additions & 5 deletions cmd/zdb/zdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
#include <sys/brt_impl.h>
#include <zfs_comutil.h>
#include <sys/zstd/zstd.h>
#include <sys/backtrace.h>

#include <libnvpair.h>
#include <libzutil.h>
Expand Down Expand Up @@ -828,11 +829,34 @@ usage(void)
static void
dump_debug_buffer(void)
{
if (dump_opt['G']) {
(void) printf("\n");
(void) fflush(stdout);
zfs_dbgmsg_print("zdb");
}
ssize_t ret __attribute__((unused));

if (!dump_opt['G'])
return;
/*
* We use write() instead of printf() so that this function
* is safe to call from a signal handler.
*/
ret = write(STDERR_FILENO, "\n", 1);
zfs_dbgmsg_print(STDERR_FILENO, "zdb");
}

static void sig_handler(int signo)
{
struct sigaction action;

libspl_backtrace(STDERR_FILENO);
dump_debug_buffer();

/*
* 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);
}

/*
Expand Down Expand Up @@ -8899,9 +8923,27 @@ main(int argc, char **argv)
char *spa_config_path_env, *objset_str;
boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE;
nvlist_t *cfg = NULL;
struct sigaction action;

dprintf_setup(&argc, argv);

/*
* Set up signal handlers, so if we crash due to bad on-disk data we
* can get more info. Unlike ztest, we don't bail out if we can't set
* up signal handlers, because zdb is very useful without them.
*/
action.sa_handler = sig_handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
if (sigaction(SIGSEGV, &action, NULL) < 0) {
(void) fprintf(stderr, "zdb: cannot catch SIGSEGV: %s\n",
strerror(errno));
}
if (sigaction(SIGABRT, &action, NULL) < 0) {
(void) fprintf(stderr, "zdb: cannot catch SIGABRT: %s\n",
strerror(errno));
}

/*
* If there is an environment variable SPA_CONFIG_PATH it overrides
* default spa_config_path setting. If -U flag is specified it will
Expand Down
17 changes: 4 additions & 13 deletions cmd/ztest.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,7 @@
#include <libzutil.h>
#include <sys/crypto/icp.h>
#include <sys/zfs_impl.h>
#if (__GLIBC__ && !__UCLIBC__)
#include <execinfo.h> /* for backtrace() */
#endif
#include <sys/backtrace.h>

static int ztest_fd_data = -1;
static int ztest_fd_rand = -1;
Expand Down Expand Up @@ -617,22 +615,15 @@ dump_debug_buffer(void)
* We use write() instead of printf() so that this function
* is safe to call from a signal handler.
*/
ret = write(STDOUT_FILENO, "\n", 1);
zfs_dbgmsg_print("ztest");
ret = write(STDERR_FILENO, "\n", 1);
zfs_dbgmsg_print(STDERR_FILENO, "ztest");
}

#define BACKTRACE_SZ 100

static void sig_handler(int signo)
{
struct sigaction action;
#if (__GLIBC__ && !__UCLIBC__) /* backtrace() is a GNU extension */
int nptrs;
void *buffer[BACKTRACE_SZ];

nptrs = backtrace(buffer, BACKTRACE_SZ);
backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
#endif
libspl_backtrace(STDERR_FILENO);
dump_debug_buffer();

/*
Expand Down
2 changes: 1 addition & 1 deletion include/sys/zfs_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ extern void zfs_dbgmsg_fini(void);

#ifndef _KERNEL
extern int dprintf_find_string(const char *string);
extern void zfs_dbgmsg_print(const char *tag);
extern void zfs_dbgmsg_print(int fd, const char *tag);
#endif

#ifdef __cplusplus
Expand Down
111 changes: 106 additions & 5 deletions lib/libnvpair/libnvpair.abi
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
<elf-symbol name='fnvpair_value_uint64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fnvpair_value_uint8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_backtrace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
Expand Down Expand Up @@ -1156,6 +1157,11 @@
<parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='strcspn' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='80f4b756'/>
Expand Down Expand Up @@ -2041,21 +2047,121 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='320' id='36c46961'>
<subrange length='40' type-id='7359adad' id='8f80b239'/>
</array-type-def>
<union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'>
<data-member access='public'>
<var-decl name='__data' type-id='4c734837' visibility='default'/>
</data-member>
<data-member access='public'>
<var-decl name='__size' type-id='36c46961' visibility='default'/>
</data-member>
<data-member access='public'>
<var-decl name='__align' type-id='bd54fe1a' visibility='default'/>
</data-member>
</union-decl>
<typedef-decl name='pthread_mutex_t' type-id='70681f9b' id='7a6844eb'/>
<class-decl name='__pthread_mutex_s' size-in-bits='320' is-struct='yes' visibility='default' id='4c734837'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='__lock' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='__count' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='__owner' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='__nusers' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='__kind' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='160'>
<var-decl name='__spins' type-id='a2185560' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='176'>
<var-decl name='__elision' type-id='a2185560' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='__list' type-id='518fb49c' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='__pthread_internal_list' size-in-bits='128' is-struct='yes' visibility='default' id='0e01899c'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='__prev' type-id='4d98cd5a' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='__next' type-id='4d98cd5a' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__pthread_list_t' type-id='0e01899c' id='518fb49c'/>
<typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/>
<pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/>
<pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/>
<function-decl name='libspl_backtrace' mangled-name='libspl_backtrace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_backtrace'>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='pthread_mutex_lock' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='18c91f9e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='pthread_mutex_unlock' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='18c91f9e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='9d26089a'/>
<parameter type-id='b7f2d5e6'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='gettid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='prctl' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/backtrace.c' language='LANG_C99'>
<typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
<typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
<pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
<function-decl name='backtrace' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='63e171df'/>
<parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='backtrace_symbols_fd' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='7acd98a2'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='write' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='b59d7dce'/>
<return type-id='79a0948f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/nvpair/fnvpair.c' language='LANG_C99'>
<function-decl name='fnvlist_alloc' mangled-name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_alloc'>
<return type-id='5ce45b60'/>
Expand Down Expand Up @@ -2536,11 +2642,6 @@
<parameter type-id='b59d7dce'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<return type-id='b59d7dce'/>
Expand Down
3 changes: 2 additions & 1 deletion lib/libspl/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ noinst_LTLIBRARIES += libspl_assert.la libspl.la
CPPCHECKTARGETS += libspl_assert.la libspl.la

libspl_assert_la_SOURCES = \
%D%/assert.c
%D%/assert.c \
%D%/backtrace.c

libspl_la_SOURCES = \
%D%/libspl_impl.h \
Expand Down
52 changes: 2 additions & 50 deletions lib/libspl/assert.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <assert.h>
#include <pthread.h>
#include <sys/backtrace.h>

#if defined(__linux__)
#include <errno.h>
Expand All @@ -51,55 +52,6 @@
pthread_getname_np(pthread_self(), buf, len);
#endif

#if defined(HAVE_LIBUNWIND)
#define UNW_LOCAL_ONLY
#include <libunwind.h>

static inline void
libspl_dump_backtrace(void)
{
unw_context_t uc;
unw_cursor_t cp;
unw_word_t ip, off;
char funcname[128];
#ifdef HAVE_LIBUNWIND_ELF
char objname[128];
unw_word_t objoff;
#endif

fprintf(stderr, "Call trace:\n");
unw_getcontext(&uc);
unw_init_local(&cp, &uc);
while (unw_step(&cp) > 0) {
unw_get_reg(&cp, UNW_REG_IP, &ip);
unw_get_proc_name(&cp, funcname, sizeof (funcname), &off);
#ifdef HAVE_LIBUNWIND_ELF
unw_get_elf_filename(&cp, objname, sizeof (objname), &objoff);
fprintf(stderr, " [0x%08lx] %s+0x%2lx (in %s +0x%2lx)\n",
ip, funcname, off, objname, objoff);
#else
fprintf(stderr, " [0x%08lx] %s+0x%2lx\n", ip, funcname, off);
#endif
}
}
#elif defined(HAVE_BACKTRACE)
#include <execinfo.h>

static inline void
libspl_dump_backtrace(void)
{
void *btptrs[100];
size_t nptrs = backtrace(btptrs, 100);
char **bt = backtrace_symbols(btptrs, nptrs);
fprintf(stderr, "Call trace:\n");
for (size_t i = 0; i < nptrs; i++)
fprintf(stderr, " %s\n", bt[i]);
free(bt);
}
#else
#define libspl_dump_backtrace()
#endif

#if defined(__APPLE__)
static inline uint64_t
libspl_gettid(void)
Expand Down Expand Up @@ -151,7 +103,7 @@ libspl_assertf(const char *file, const char *func, int line,
getpid(), libspl_getprogname(),
libspl_gettid(), tname);

libspl_dump_backtrace();
libspl_backtrace(STDERR_FILENO);

#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__)
if (libspl_assert_ok) {
Expand Down
Loading
Loading