Skip to content

Commit 2152c40

Browse files
robnbehlendorf
authored andcommitted
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 openzfs#16140
1 parent dec697a commit 2152c40

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

config/user-backtrace.m4

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
dnl
2+
dnl backtrace(), for userspace assertions. glibc has this directly in libc.
3+
dnl FreeBSD and (sometimes) musl have it in a separate -lexecinfo. It's assumed
4+
dnl that this will also get the companion function backtrace_symbols().
5+
dnl
6+
AC_DEFUN([ZFS_AC_CONFIG_USER_BACKTRACE], [
7+
AX_SAVE_FLAGS
8+
LIBS=""
9+
AC_SEARCH_LIBS([backtrace], [execinfo], [
10+
AC_DEFINE(HAVE_BACKTRACE, 1, [backtrace() is available])
11+
AC_SUBST([BACKTRACE_LIBS], ["$LIBS"])
12+
])
13+
AX_RESTORE_FLAGS
14+
])

config/user.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
2626
ZFS_AC_CONFIG_USER_AIO_H
2727
ZFS_AC_CONFIG_USER_CLOCK_GETTIME
2828
ZFS_AC_CONFIG_USER_PAM
29+
ZFS_AC_CONFIG_USER_BACKTRACE
2930
ZFS_AC_CONFIG_USER_RUNSTATEDIR
3031
ZFS_AC_CONFIG_USER_MAKEDEV_IN_SYSMACROS
3132
ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV

lib/libspl/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,5 @@ libspl_la_LIBADD = \
4343
libspl_assert.la
4444

4545
libspl_la_LIBADD += $(LIBATOMIC_LIBS) $(LIBCLOCK_GETTIME)
46+
47+
libspl_assert_la_LIBADD = $(BACKTRACE_LIBS)

lib/libspl/assert.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@
4949
pthread_getname_np(pthread_self(), buf, len);
5050
#endif
5151

52+
#if defined(HAVE_BACKTRACE)
53+
#include <execinfo.h>
54+
55+
static inline void
56+
libspl_dump_backtrace(void)
57+
{
58+
void *btptrs[100];
59+
size_t nptrs = backtrace(btptrs, 100);
60+
char **bt = backtrace_symbols(btptrs, nptrs);
61+
fprintf(stderr, "Call trace:\n");
62+
for (size_t i = 0; i < nptrs; i++)
63+
fprintf(stderr, " %s\n", bt[i]);
64+
free(bt);
65+
}
66+
#else
67+
#define libspl_dump_backtrace()
68+
#endif
69+
5270
static boolean_t libspl_assert_ok = B_FALSE;
5371

5472
void
@@ -83,6 +101,8 @@ libspl_assertf(const char *file, const char *func, int line,
83101
getpid(), libspl_getprogname(),
84102
libspl_gettid(), tname);
85103

104+
libspl_dump_backtrace();
105+
86106
#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__)
87107
if (libspl_assert_ok) {
88108
pthread_mutex_unlock(&assert_lock);

0 commit comments

Comments
 (0)