From 2152c405ba6ab0bc9fca482e9a0a968eb35699fb Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Sat, 27 Apr 2024 21:35:05 +1000 Subject: 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 Signed-off-by: Rob Norris Sponsored-by: https://despairlabs.com/sponsor/ Closes #16140 --- lib/libspl/Makefile.am | 2 ++ lib/libspl/assert.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'lib') 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 + +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); -- cgit v1.2.3