From c49a46ca8adc933f4bea922d6197e8903b686d31 Mon Sep 17 00:00:00 2001 From: malavan Date: Mon, 19 Jul 2021 17:20:52 +0000 Subject: [PATCH 1/6] add backtrace for alpine using libunwind Former-commit-id: c583ffff412b9df705b7c96e68e3908b645c7d43 --- src/Makefile | 13 ++++++++--- src/debug.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index 37f7ba917..c8075236e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -127,7 +127,7 @@ ifneq ($(uname_S),Darwin) endif # Linux ARM32 needs -latomic at linking time ifneq (,$(findstring armv,$(uname_M))) - FINAL_LIBS+=-latomic + FINAL_LIBS+=-latomic endif @@ -177,7 +177,7 @@ ifeq ($(uname_S),OpenBSD) FINAL_CXXFLAGS+= -DUSE_BACKTRACE -I/usr/local/include FINAL_LDFLAGS+= -L/usr/local/lib FINAL_LIBS+= -lexecinfo - endif + endif else ifeq ($(uname_S),NetBSD) @@ -187,7 +187,7 @@ ifeq ($(uname_S),NetBSD) FINAL_CFLAGS+= -DUSE_BACKTRACE -I/usr/pkg/include FINAL_LDFLAGS+= -L/usr/pkg/lib FINAL_LIBS+= -lexecinfo - endif + endif else ifeq ($(uname_S),FreeBSD) # FreeBSD @@ -316,6 +316,13 @@ else endef endif +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 diff --git a/src/debug.cpp b/src/debug.cpp index 7b7fe29e1..7a2c16255 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -51,6 +51,11 @@ typedef ucontext_t sigcontext_t; #include #endif /* HAVE_BACKTRACE */ +#ifdef UNW_LOCAL_ONLY +#include +#include +#endif + #ifdef __CYGWIN__ #ifndef SA_ONSTACK #define SA_ONSTACK 0x08000000 @@ -947,7 +952,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 +1049,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 +1604,52 @@ void safe_write(int fd, const void *pv, ssize_t cb) } while (offset < cb); } +#ifdef UNW_LOCAL_ONLY + +void logStackTrace(void *eip, int uplevel) { + int fd = openDirectLogFiledes(); + + if (fd == -1) return; /* If we can't log there is anything to do. */ + unw_cursor_t cursor; + unw_context_t context; + + unw_getcontext(&context); + unw_init_local(&cursor, &context); + + 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] = {""}; + 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(off), + static_cast(ip), + static_cast(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 +1693,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 +1983,9 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) { logRegisters(uc); #endif +#ifdef UNW_LOCAL_ONLY + logStackTrace(NULL, 1); +#endif printCrashReport(); @@ -2028,6 +2080,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 From 7d4b4139588d9f2f1b100a8216f75f38748f855a Mon Sep 17 00:00:00 2001 From: malavan Date: Mon, 19 Jul 2021 17:29:43 +0000 Subject: [PATCH 2/6] dd comment and set eip unused Former-commit-id: 7707fe15a9c9774820b3afb9837a50e73c40a5a8 --- src/debug.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/debug.cpp b/src/debug.cpp index 7a2c16255..1a0926c9d 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -1606,7 +1606,11 @@ void safe_write(int fd, const void *pv, ssize_t cb) #ifdef UNW_LOCAL_ONLY -void logStackTrace(void *eip, int uplevel) { +/* 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 * __unused eip, int uplevel) { int fd = openDirectLogFiledes(); if (fd == -1) return; /* If we can't log there is anything to do. */ From 4bc552fba2eefa73be96fd6d2e97d76d5e4a36d8 Mon Sep 17 00:00:00 2001 From: malavan Date: Mon, 19 Jul 2021 17:31:24 +0000 Subject: [PATCH 3/6] dd comment and set eip unused Former-commit-id: 72429c21067318696897c26783f654eb7bc6040f --- src/debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug.cpp b/src/debug.cpp index 1a0926c9d..7a7226589 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -1610,7 +1610,7 @@ void safe_write(int fd, const void *pv, ssize_t cb) * 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 * __unused eip, int uplevel) { +void logStackTrace(UNUSED void * eip, int uplevel) { int fd = openDirectLogFiledes(); if (fd == -1) return; /* If we can't log there is anything to do. */ From fe2292f1119d732f3d1bc5e583715956e7c0f34d Mon Sep 17 00:00:00 2001 From: malavan Date: Mon, 19 Jul 2021 17:32:38 +0000 Subject: [PATCH 4/6] dd comment and set eip unused Former-commit-id: 685b87e2ef4f67cd599b12e38b08f5b70b7a6c58 --- src/debug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/debug.cpp b/src/debug.cpp index 7a7226589..d74772c29 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -1610,7 +1610,8 @@ void safe_write(int fd, const void *pv, ssize_t cb) * 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(UNUSED void * eip, int uplevel) { +void logStackTrace(void * eip, int uplevel) { + (void)eip;//UNUSED int fd = openDirectLogFiledes(); if (fd == -1) return; /* If we can't log there is anything to do. */ From a269f35002df02e2ea40df5565b7e21cf81a801c Mon Sep 17 00:00:00 2001 From: malavan Date: Mon, 19 Jul 2021 23:17:18 +0000 Subject: [PATCH 5/6] add stacktrace message Former-commit-id: 5be1620629ce8de7f419bc001f18d22d6eb4fa8a --- src/debug.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/debug.cpp b/src/debug.cpp index d74772c29..39a22e297 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -1612,15 +1612,23 @@ void safe_write(int fd, const void *pv, ssize_t cb) */ 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); } From c3a6be36e3288375dd185c23253d13aa94600908 Mon Sep 17 00:00:00 2001 From: malavan Date: Wed, 28 Jul 2021 20:32:18 +0000 Subject: [PATCH 6/6] add some comments Former-commit-id: 0fc6441c9608f0650003a7ab29dd704166345272 --- src/Makefile | 1 + src/debug.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index c8075236e..75dffb24e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -316,6 +316,7 @@ 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 diff --git a/src/debug.cpp b/src/debug.cpp index 39a22e297..a9614b61e 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -51,6 +51,7 @@ typedef ucontext_t sigcontext_t; #include #endif /* HAVE_BACKTRACE */ +//UNW_LOCAL_ONLY being set means we use libunwind for backtraces instead of execinfo #ifdef UNW_LOCAL_ONLY #include #include