]> git.proxmox.com Git - mirror_zfs.git/commitdiff
libspl/assert: dump backtrace in assert
authorRob Norris <robn@despairlabs.com>
Sat, 27 Apr 2024 11:35:05 +0000 (21:35 +1000)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 1 May 2024 17:52:00 +0000 (10:52 -0700)
Adds a check for the backtrace() function. If available, uses it to show
a stack backtrace in the assertion output.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Sponsored-by: https://despairlabs.com/sponsor/
Closes #16140

config/user-backtrace.m4 [new file with mode: 0644]
config/user.m4
lib/libspl/Makefile.am
lib/libspl/assert.c

diff --git a/config/user-backtrace.m4 b/config/user-backtrace.m4
new file mode 100644 (file)
index 0000000..2570676
--- /dev/null
@@ -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
+])
index 3a69086a9d9da01b6d1923e2b4c2218e1074be46..8d11e031ba2eb211e19f9b00811d254bca1ef80d 100644 (file)
@@ -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
index 822bef7e7a8d91f6868a647e16ccfffb7cf8548b..9f413b08c16f49a246d605a7be402f18ef3b2a84 100644 (file)
@@ -43,3 +43,5 @@ libspl_la_LIBADD = \
        libspl_assert.la
 
 libspl_la_LIBADD += $(LIBATOMIC_LIBS) $(LIBCLOCK_GETTIME)
+
+libspl_assert_la_LIBADD = $(BACKTRACE_LIBS)
index d402462531b6d0530b80f7d41dce76d027f97491..4acf687f4b237ee0444218c61b7f578cf5a96585 100644 (file)
        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);