Merge pull request #328 from EQ-Alpha/backtrace_for_alpine
Backtrace for alpine using libunwind Former-commit-id: 83d878f11183d8cd54fb34bceb7f839f73599ab1
This commit is contained in:
commit
31e2a22b6f
@ -316,6 +316,14 @@ else
|
||||
endef
|
||||
endif
|
||||
|
||||
# Alpine OS doesn't have support for the execinfo backtrace library we use for debug, so we provide an alternate implementation using libwunwind.
|
||||
OS := $(shell cat /etc/os-release | grep ID= | head -n 1 | cut -d'=' -f2)
|
||||
ifeq ($(OS),alpine)
|
||||
FINAL_CXXFLAGS+=-DUNW_LOCAL_ONLY
|
||||
FINAL_LIBS += -lunwind
|
||||
endif
|
||||
|
||||
|
||||
REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)
|
||||
REDIS_CXX=$(QUIET_CC)$(CXX) $(FINAL_CXXFLAGS)
|
||||
KEYDB_AS=$(QUIET_CC) as --64 -g
|
||||
|
@ -51,6 +51,12 @@ typedef ucontext_t sigcontext_t;
|
||||
#include <cxxabi.h>
|
||||
#endif /* HAVE_BACKTRACE */
|
||||
|
||||
//UNW_LOCAL_ONLY being set means we use libunwind for backtraces instead of execinfo
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#ifndef SA_ONSTACK
|
||||
#define SA_ONSTACK 0x08000000
|
||||
@ -947,7 +953,7 @@ void _serverAssert(const char *estr, const char *file, int line) {
|
||||
serverLog(LL_WARNING,"==> %s:%d '%s' is not true",file,line,estr);
|
||||
|
||||
if (g_pserver->crashlog_enabled) {
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#if defined HAVE_BACKTRACE || defined UNW_LOCAL_ONLY
|
||||
logStackTrace(NULL, 1);
|
||||
#endif
|
||||
printCrashReport();
|
||||
@ -1044,7 +1050,7 @@ void _serverPanic(const char *file, int line, const char *msg, ...) {
|
||||
serverLog(LL_WARNING,"Guru Meditation: %s #%s:%d",fmtmsg,file,line);
|
||||
|
||||
if (g_pserver->crashlog_enabled) {
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#if defined HAVE_BACKTRACE || defined UNW_LOCAL_ONLY
|
||||
logStackTrace(NULL, 1);
|
||||
#endif
|
||||
printCrashReport();
|
||||
@ -1599,6 +1605,65 @@ void safe_write(int fd, const void *pv, ssize_t cb)
|
||||
} while (offset < cb);
|
||||
}
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
||||
/* Logs the stack trace using the libunwind call.
|
||||
* The eip argument is unused as libunwind only gets local context.
|
||||
* The uplevel argument indicates how many of the calling functions to skip.
|
||||
*/
|
||||
void logStackTrace(void * eip, int uplevel) {
|
||||
(void)eip;//UNUSED
|
||||
const char *msg;
|
||||
int fd = openDirectLogFiledes();
|
||||
|
||||
if (fd == -1) return; /* If we can't log there is anything to do. */
|
||||
|
||||
msg = "\n------ STACK TRACE ------\n";
|
||||
if (write(fd,msg,strlen(msg)) == -1) {/* Avoid warning. */};
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
|
||||
unw_getcontext(&context);
|
||||
unw_init_local(&cursor, &context);
|
||||
|
||||
/* Write symbols to log file */
|
||||
msg = "\nBacktrace:\n";
|
||||
if (write(fd,msg,strlen(msg)) == -1) {/* Avoid warning. */};
|
||||
|
||||
for (int i = 0; i < uplevel; i++) {
|
||||
unw_step(&cursor);
|
||||
}
|
||||
|
||||
while ( unw_step(&cursor) ) {
|
||||
unw_word_t ip, sp, off;
|
||||
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
unw_get_reg(&cursor, UNW_REG_SP, &sp);
|
||||
|
||||
char symbol[256] = {"<unknown>"};
|
||||
char *name = symbol;
|
||||
|
||||
if ( !unw_get_proc_name(&cursor, symbol, sizeof(symbol), &off) ) {
|
||||
int status;
|
||||
if ( (name = abi::__cxa_demangle(symbol, NULL, NULL, &status)) == 0 )
|
||||
name = symbol;
|
||||
}
|
||||
|
||||
dprintf(fd, "%s(+0x%" PRIxPTR ") [0x%016" PRIxPTR "] sp=0x%016" PRIxPTR "\n",
|
||||
name,
|
||||
static_cast<uintptr_t>(off),
|
||||
static_cast<uintptr_t>(ip),
|
||||
static_cast<uintptr_t>(sp));
|
||||
|
||||
if ( name != symbol )
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* UNW_LOCAL_ONLY */
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
|
||||
void backtrace_symbols_demangle_fd(void **trace, size_t csym, int fd)
|
||||
{
|
||||
char **syms = backtrace_symbols(trace, csym);
|
||||
@ -1642,8 +1707,6 @@ void backtrace_symbols_demangle_fd(void **trace, size_t csym, int fd)
|
||||
free(syms);
|
||||
}
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
|
||||
/* Logs the stack trace using the backtrace() call. This function is designed
|
||||
* to be called from signal handlers safely.
|
||||
* The eip argument is optional (can take NULL).
|
||||
@ -1934,6 +1997,9 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
|
||||
|
||||
logRegisters(uc);
|
||||
#endif
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
logStackTrace(NULL, 1);
|
||||
#endif
|
||||
|
||||
printCrashReport();
|
||||
|
||||
@ -2028,6 +2094,8 @@ void watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {
|
||||
serverLogFromHandler(LL_WARNING,"\n--- WATCHDOG TIMER EXPIRED ---");
|
||||
#ifdef HAVE_BACKTRACE
|
||||
logStackTrace(getMcontextEip(uc), 1);
|
||||
#elif defined UNW_LOCAL_ONLY
|
||||
logStackTrace(NULL, 1);
|
||||
#else
|
||||
serverLogFromHandler(LL_WARNING,"Sorry: no support for backtrace().");
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user