libspl/assert: show process/task details in assert output

Makes it much easier to see what thing complained.

Getting thread id, program name and thread name vary wildly between
Linux and FreeBSD, so those are set up in macros. pthread_getname_np()
did not appear in musl until very recently, but the same info has always
been available via prctl(PR_GET_NAME), so we use that instead.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Sponsored-by: https://despairlabs.com/sponsor/
Closes #16140
This commit is contained in:
Rob Norris 2024-04-21 21:43:53 +10:00 committed by Tony Hutter
parent 5668411713
commit 96cad4ca4c
2 changed files with 35 additions and 3 deletions

View File

@ -31,7 +31,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV
ZFS_AC_CONFIG_USER_ZFSEXEC ZFS_AC_CONFIG_USER_ZFSEXEC
AC_CHECK_FUNCS([execvpe issetugid mlockall strlcat strlcpy]) AC_CHECK_FUNCS([execvpe issetugid mlockall strlcat strlcpy gettid])
AC_SUBST(RM) AC_SUBST(RM)
]) ])

View File

@ -22,9 +22,32 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms. * Use is subject to license terms.
*/ */
/*
* Copyright (c) 2024, Rob Norris <robn@despairlabs.com>
*/
#include <assert.h> #include <assert.h>
#if defined(__linux__)
#include <errno.h>
#include <sys/prctl.h>
#ifdef HAVE_GETTID
#define libspl_gettid() gettid()
#else
#include <sys/syscall.h>
#define libspl_gettid() ((pid_t)syscall(__NR_gettid))
#endif
#define libspl_getprogname() (program_invocation_short_name)
#define libspl_getthreadname(buf, len) \
prctl(PR_GET_NAME, (unsigned long)(buf), 0, 0, 0)
#elif defined(__FreeBSD__)
#include <pthread_np.h>
#define libspl_gettid() pthread_getthreadid_np()
#define libspl_getprogname() getprogname()
#define libspl_getthreadname(buf, len) \
pthread_getname_np(pthread_self(), buf, len);
#endif
static boolean_t libspl_assert_ok = B_FALSE; static boolean_t libspl_assert_ok = B_FALSE;
void void
@ -39,13 +62,22 @@ libspl_assertf(const char *file, const char *func, int line,
const char *format, ...) const char *format, ...)
{ {
va_list args; va_list args;
char tname[64];
libspl_getthreadname(tname, sizeof (tname));
fprintf(stderr, "ASSERT at %s:%d:%s()\n", file, line, func);
va_start(args, format); va_start(args, format);
vfprintf(stderr, format, args); vfprintf(stderr, format, args);
fprintf(stderr, "\n");
fprintf(stderr, "ASSERT at %s:%d:%s()", file, line, func);
va_end(args); va_end(args);
fprintf(stderr, "\n"
" PID: %-8u COMM: %s\n"
" TID: %-8u NAME: %s\n",
getpid(), libspl_getprogname(),
libspl_gettid(), tname);
#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__) #if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__)
if (libspl_assert_ok) { if (libspl_assert_ok) {
return; return;