diff options
author | Rob Norris <[email protected]> | 2024-04-27 21:35:05 +1000 |
---|---|---|
committer | Tony Hutter <[email protected]> | 2024-07-17 14:54:46 -0700 |
commit | 21f66db67432ad9f6363d0e69fcabb53976a45e4 (patch) | |
tree | 0a70e3b3f998170fbc7561d7bb1a5052a400af2d | |
parent | 3ca305f87377afeeb3006ee6fe053358dc2f1ad8 (diff) |
libspl/assert: dump backtrace in assert
Adds a check for the backtrace() function. If available, uses it to show
a stack backtrace in the assertion output.
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Rob Norris <[email protected]>
Sponsored-by: https://despairlabs.com/sponsor/
Closes #16140
-rw-r--r-- | config/user-backtrace.m4 | 14 | ||||
-rw-r--r-- | config/user.m4 | 1 | ||||
-rw-r--r-- | lib/libspl/Makefile.am | 2 | ||||
-rw-r--r-- | lib/libspl/assert.c | 20 |
4 files changed, 37 insertions, 0 deletions
diff --git a/config/user-backtrace.m4 b/config/user-backtrace.m4 new file mode 100644 index 000000000..25706767c --- /dev/null +++ b/config/user-backtrace.m4 @@ -0,0 +1,14 @@ +dnl +dnl backtrace(), for userspace assertions. glibc has this directly in libc. +dnl FreeBSD and (sometimes) musl have it in a separate -lexecinfo. It's assumed +dnl that this will also get the companion function backtrace_symbols(). +dnl +AC_DEFUN([ZFS_AC_CONFIG_USER_BACKTRACE], [ + AX_SAVE_FLAGS + LIBS="" + AC_SEARCH_LIBS([backtrace], [execinfo], [ + AC_DEFINE(HAVE_BACKTRACE, 1, [backtrace() is available]) + AC_SUBST([BACKTRACE_LIBS], ["$LIBS"]) + ]) + AX_RESTORE_FLAGS +]) diff --git a/config/user.m4 b/config/user.m4 index 3a69086a9..8d11e031b 100644 --- a/config/user.m4 +++ b/config/user.m4 @@ -26,6 +26,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [ ZFS_AC_CONFIG_USER_AIO_H ZFS_AC_CONFIG_USER_CLOCK_GETTIME ZFS_AC_CONFIG_USER_PAM + ZFS_AC_CONFIG_USER_BACKTRACE ZFS_AC_CONFIG_USER_RUNSTATEDIR ZFS_AC_CONFIG_USER_MAKEDEV_IN_SYSMACROS ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am index 822bef7e7..9f413b08c 100644 --- a/lib/libspl/Makefile.am +++ b/lib/libspl/Makefile.am @@ -43,3 +43,5 @@ libspl_la_LIBADD = \ libspl_assert.la libspl_la_LIBADD += $(LIBATOMIC_LIBS) $(LIBCLOCK_GETTIME) + +libspl_assert_la_LIBADD = $(BACKTRACE_LIBS) diff --git a/lib/libspl/assert.c b/lib/libspl/assert.c index d40246253..4acf687f4 100644 --- a/lib/libspl/assert.c +++ b/lib/libspl/assert.c @@ -49,6 +49,24 @@ pthread_getname_np(pthread_self(), buf, len); #endif +#if 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 + static boolean_t libspl_assert_ok = B_FALSE; void @@ -83,6 +101,8 @@ libspl_assertf(const char *file, const char *func, int line, getpid(), libspl_getprogname(), libspl_gettid(), tname); + libspl_dump_backtrace(); + #if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__) if (libspl_assert_ok) { pthread_mutex_unlock(&assert_lock); |