Skip to content

Commit

Permalink
Enable libunwind in ganesha
Browse files Browse the repository at this point in the history
Currently, Ganesha uses backtrace during crashes,
which may not provide sufficient useful information:
07/02/2024 19:09:18: epoch 65c3d55b: xueqian-hu: nfs-ganesha-39008[main] gsh_backtrace: NFS STARTUP: MAJ: stack
backtrace follows:
/lib64/libganesha_nfsd.so.5.6(+0x83ba1)[0x7f64d9172ba1]
/lib64/libganesha_nfsd.so.5.6(+0x5d618)[0x7f64d914c618]
/lib64/libpthread.so.0(+0xf630)[0x7f64d7d1a630]
/lib64/libpthread.so.0(pthread_join+0xa7)[0x7f64d7d14017]
/lib64/libganesha_nfsd.so.5.6(nfs_start+0x323)[0x7f64d914eff3]
ganesha.nfsd(main+0xbef)[0x4025cf]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f64d753d555]
ganesha.nfsd[0x402663]

This patch introduces an option to use libunwind, which can display function information:
08/02/2024 20:06:04: epoch 65c53429: xueqian-hu: nfs-ganesha-99814[main] gsh_libunwind: NFS STARTUP: MAJ: BACKTRACE:
08/02/2024 20:06:04 : epoch 65c53429 : xueqian-hu : nfs-ganesha-99814[main] gsh_libunwind :NFS STARTUP :MAJ :BACKTRACE:
 #0 gsh_libunwind + 0x29 [ip=0x7f90b1a10859] [sp=0x7ffd49d53c00]
 #1 crash_handler + 0x8 [ip=0x7f90b19e9fd8] [sp=0x7ffd49d54670]
 #2 _L_unlock_13 + 0x34 [ip=0x7f90b039d630] [sp=0x7ffd49d54680]
 #3 pthread_join + 0xa7 [ip=0x7f90b0397017] [sp=0x7ffd49d55380]
 #4 nfs_start + 0x323 [ip=0x7f90b19ec9b3] [sp=0x7ffd49d553e0]
 #5 main + 0xbef [ip=0x4025df] [sp=0x7ffd49d55480]

Change-Id: I194853e25ec0c89c7f552dc4872c37a420ea8d4a
Signed-off-by: Xueqian Hu <xh140312@outlook.com>
  • Loading branch information
xueqianhu47 authored and ffilz committed Feb 22, 2024
1 parent 51ad56d commit 158f395
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,21 @@ add_custom_command(TARGET srpm

# Roll up required libraries

# enable libunwind if available
goption(USE_UNWIND "Enable libunwind" ON)
gopt_test(USE_UNWIND)
if (USE_UNWIND)
find_package(Unwind)
if (UNWIND_FOUND)
set(SYSTEM_LIBRARIES ${UNWIND_LIBRARIES} ${SYSTEM_LIBRARIES})
include_directories(${UNWIND_INCLUDE_DIR})
message(STATUS "libunwind found: ${UNWIND_LIBRARIES}")
else (UNWIND_FOUND)
message(WARNING "libunwind not found. Disabling USE_UNWIND")
set(USE_UNWIND OFF)
endif (UNWIND_FOUND)
endif(USE_UNWIND)

if(USE_9P_RDMA)
find_package(PkgConfig)
pkg_check_modules(MOOSHIKA REQUIRED libmooshika>=0.6)
Expand Down Expand Up @@ -1381,6 +1396,7 @@ message(STATUS "USE_MAN_PAGE = ${USE_MAN_PAGE}")
message(STATUS "USE_RADOS_RECOV = ${USE_RADOS_RECOV}")
message(STATUS "RADOS_URLS = ${RADOS_URLS}")
message(STATUS "USE_CUNIT = ${USE_CUNIT}")
message(STATUS "USE_UNWIND = ${USE_UNWIND}")
message(STATUS "SANITIZE_ADDRESS = ${SANITIZE_ADDRESS}")

set(USE_CB_SIMULATOR ${USE_CB_SIMULATOR}
Expand Down Expand Up @@ -1608,6 +1624,12 @@ else(RPCBIND)
set(BCOND_RPCBIND "%bcond_with")
endif(RPCBIND)

if(USE_UNWIND)
set(BCOND_UNWIND "%bcond_without")
else(USE_UNWIND)
set(BCOND_UNWIND "%bcond_with")
endif(USE_UNWIND)

if(_MSPAC_SUPPORT)
set(BCOND_MSPAC_SUPPORT "%bcond_without")
else(_MSPAC_SUPPORT)
Expand Down
4 changes: 4 additions & 0 deletions src/MainNFSD/nfs_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,11 @@ static void *sigmgr_thread(void *UnusedArg)

static void crash_handler(int signo, siginfo_t *info, void *ctx)
{
#ifdef USE_UNWIND
gsh_libunwind();
#else
gsh_backtrace();
#endif
/* re-raise the signal for the default signal handler to dump core */
raise(signo);
}
Expand Down
27 changes: 27 additions & 0 deletions src/cmake/modules/FindUnwind.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# FindUnwind.cmake

if(UNWIND_PATH_HINT)
message(STATUS "Using UNWIND_PATH_HINT: ${UNWIND_PATH_HINT}")
else()
set(UNWIND_PATH_HINT)
endif()

find_path(UNWIND_INCLUDE_DIR
NAMES libunwind.h
PATHS ${UNWIND_PATH_HINT}
PATH_SUFFIXES include
DOC "The libunwind include directory")

find_library(UNWIND_LIBRARY
NAMES unwind
PATHS ${UNWIND_PATH_HINT}
PATH_SUFFIXES lib lib64
DOC "The libunwind library")

set(UNWIND_LIBRARIES ${UNWIND_LIBRARY})

include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Unwind REQUIRED_VARS UNWIND_LIBRARY UNWIND_INCLUDE_DIR)

mark_as_advanced(UNWIND_INCLUDE_DIR UNWIND_LIBRARY)

1 change: 1 addition & 0 deletions src/include/config-h.in.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#cmakedefine _MSPAC_SUPPORT 1
#cmakedefine USE_NFSIDMAP 1
#cmakedefine USE_DBUS 1
#cmakedefine USE_UNWIND 1
#cmakedefine _USE_CB_SIMULATOR 1
#cmakedefine USE_CAPS 1
#cmakedefine USE_BLKID 1
Expand Down
4 changes: 4 additions & 0 deletions src/include/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ void LogMallocFailure(const char *file, int line, const char *function,
int read_log_config(config_file_t in_config,
struct config_error_type *err_type);

#ifdef USE_UNWIND
void gsh_libunwind(void);
#endif

void gsh_backtrace(void);

/* These functions display a timeval or timespec into the display buffer
Expand Down
93 changes: 93 additions & 0 deletions src/log/log_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
#include <execinfo.h>
#include <assert.h>

#ifdef USE_UNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#endif

#include "log.h"
#include "gsh_list.h"
#include "gsh_rpc.h"
Expand Down Expand Up @@ -2632,6 +2637,94 @@ int read_log_config(config_file_t in_config,
return -1;
} /* read_log_config */

#ifdef USE_UNWIND
void gsh_libunwind(void)
{
unw_cursor_t cursor;
unw_context_t uc;
unsigned int i = 0;
char procname[256];
unw_word_t ip, sp, off;

struct log_facility *facility;
struct glist_head *glist;
int fd = -1;
char buffer[256];
int n;

procname[sizeof(procname) - 1] = '\0';

if (unw_getcontext(&uc) != 0)
goto libunwind_failed;

if (unw_init_local(&cursor, &uc) != 0)
goto libunwind_failed;

/* Find an active log facility */
PTHREAD_RWLOCK_rdlock(&log_rwlock);
glist_for_each(glist, &active_facility_list) {
facility = glist_entry(glist, struct log_facility, lf_active);
if (facility->lf_func == log_to_file) {
fd = open((char *)facility->lf_private,
O_WRONLY | O_APPEND | O_CREAT, log_mask);
break;
}
}

LogMajor(COMPONENT_INIT, "BACKTRACE:");

do {
ip = sp = 0;
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
switch (unw_get_proc_name(&cursor,
procname, sizeof(procname) - 1, &off)) {
case 0:
/* Name found. */
case -UNW_ENOMEM:
/* Name truncated. */
if (fd != -1) {
n = snprintf(buffer, sizeof(buffer),
" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
i, procname, (long long)off,
(long long)ip, (long long) sp);
write(fd, buffer, n);
} else {
LogMajor(COMPONENT_INIT,
" #%u %s + %#llx [ip=%#llx] [sp=%#llx]",
i, procname, (long long)off,
(long long)ip, (long long) sp);
}
break;
default:
/* case -UNW_ENOINFO: */
/* case -UNW_EUNSPEC: */
if (fd != -1) {
snprintf(buffer, sizeof(buffer),
" #%u %s [ip=%#llx] [sp=%#llx]\n",
i, "<unknown symbol>",
(long long)ip, (long long) sp);
write(fd, buffer, n);
} else {
LogMajor(COMPONENT_INIT,
" #%u %s [ip=%#llx] [sp=%#llx]",
i, "<unknown symbol>",
(long long)ip, (long long) sp);
}
}
++i;
} while (unw_step(&cursor) > 0);

PTHREAD_RWLOCK_unlock(&log_rwlock);
return;

libunwind_failed:
LogCrit(COMPONENT_INIT,
"unable to produce a stack trace with libunwind");
}

#endif

void gsh_backtrace(void)
{
#define MAX_STACK_DEPTH 32 /* enough ? */
Expand Down
15 changes: 15 additions & 0 deletions src/nfs-ganesha.spec-in.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ Requires: openSUSE-release
@BCOND_RPCBIND@ rpcbind
%global use_rpcbind %{on_off_switch rpcbind}

@BCOND_UNWIND@ unwind
%global use_unwind %{on_off_switch unwind}

@BCOND_MSPAC_SUPPORT@ mspac_support
%global use_mspac_support %{on_off_switch mspac_support}

Expand Down Expand Up @@ -270,6 +273,17 @@ BuildRequires: python3-installer
%endif
%endif

%if %{with unwind}
%if ( 0%{?rhel} && 0%{?rhel} < 8 )
Requires: libc6-dev
%else
Requires: libc-devel
%endif
%if ( 0%{?suse_version} )
Requires: glibc-devel
%endif
%endif

%if %{with gui_utils}
%if ( 0%{?suse_version} )
BuildRequires: python-qt5-devel
Expand Down Expand Up @@ -529,6 +543,7 @@ cmake . -DCMAKE_BUILD_TYPE=Debug \
-DUSE_SYSTEM_NTIRPC=%{use_system_ntirpc} \
-DUSE_9P_RDMA=%{use_rdma} \
-DUSE_LTTNG=%{use_lttng} \
-DUSE_UNWIND=%{use_unwind} \
-DUSE_ADMIN_TOOLS=%{use_utils} \
-DUSE_GUI_ADMIN_TOOLS=%{use_gui_utils} \
-DUSE_RADOS_RECOV=%{use_rados_recov} \
Expand Down

0 comments on commit 158f395

Please sign in to comment.