From 69557c650e56bcbb5b760bb4f47c7be9953203ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sat, 30 Sep 2017 12:37:40 +0300 Subject: [PATCH] Fix stack trace generation The stack traces weren't logged as the LOG_ALERT priority wasn't enabled by default. As an alert is intended to be something that must leave a trace somewhere, and as such, it must not be possible to disable it. For this reason, it is acceptable to always log the message if the priority is LOG_ALERT. Added the -rdynamic linker flag so that all symbols are exported when linking MaxScale. As the stack trace is printed in a signal handler, the first attempt should be to print the stack trace to the standard output. This way the output is printed before an attempt to use malloc is made when it is logged to the logfile. --- CMakeLists.txt | 2 +- include/maxscale/log_manager.h | 2 +- server/core/gateway.cc | 35 ++++++++++++++++------------------ 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c98aa7f62..e9f8b7813 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,7 +144,7 @@ configure_file(${CMAKE_SOURCE_DIR}/etc/postrm.in ${CMAKE_BINARY_DIR}/postrm @ONL configure_file(${CMAKE_SOURCE_DIR}/etc/upstart/maxscale.conf.in ${CMAKE_BINARY_DIR}/upstart/maxscale.conf @ONLY) configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.cnf ${CMAKE_BINARY_DIR}/maxscale.cnf @ONLY) -set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags") +set(FLAGS "-rdynamic -Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags") set(DEBUG_FLAGS "-ggdb -pthread -pipe -Wformat -fstack-protector --param=ssp-buffer-size=4" CACHE STRING "Debug compilation flags") if(CMAKE_VERSION VERSION_GREATER 2.6) diff --git a/include/maxscale/log_manager.h b/include/maxscale/log_manager.h index 329155dc7..4f2acf64d 100644 --- a/include/maxscale/log_manager.h +++ b/include/maxscale/log_manager.h @@ -109,7 +109,7 @@ void mxs_log_get_throttling(MXS_LOG_THROTTLING* throttling); static inline bool mxs_log_priority_is_enabled(int priority) { assert((priority & ~LOG_PRIMASK) == 0); - return MXS_LOG_PRIORITY_IS_ENABLED(priority); + return MXS_LOG_PRIORITY_IS_ENABLED(priority) || priority == LOG_ALERT; } int mxs_log_message(int priority, diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 0c838245c..da4aefd08 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -398,32 +398,31 @@ sigfatal_handler(int i) } fatal_handling = 1; MXS_CONFIG* cnf = config_get_global_options(); - fprintf(stderr, "\n\nMaxScale " MAXSCALE_VERSION " received fatal signal %d\n", i); + fprintf(stderr, "Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. " + "Attempting backtrace.\n", i); + fprintf(stderr, "Commit ID: %s System name: %s Release string: %s\n\n", + maxscale_commit, cnf->sysname, cnf->release_string); + void *addrs[128]; + int count = backtrace(addrs, 128); - MXS_ALERT("Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. Attempting backtrace.", i); + // First print the stack trace to stderr as malloc is likely broken + backtrace_symbols_fd(addrs, count, STDERR_FILENO); + MXS_ALERT("Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. " + "Attempting backtrace.", i); MXS_ALERT("Commit ID: %s System name: %s " "Release string: %s", maxscale_commit, cnf->sysname, cnf->release_string); + // Then see if we can log them + char** symbols = backtrace_symbols(addrs, count); + if (symbols) { - void *addrs[128]; - int count = backtrace(addrs, 128); - char** symbols = backtrace_symbols(addrs, count); - - if (symbols) + for (int n = 0; n < count; n++) { - for (int n = 0; n < count; n++) - { - MXS_ALERT(" %s\n", symbols[n]); - } - MXS_FREE(symbols); - } - else - { - fprintf(stderr, "\nresolving symbols to error log failed, writing call trace to stderr:\n"); - backtrace_symbols_fd(addrs, count, fileno(stderr)); + MXS_ALERT(" %s\n", symbols[n]); } + MXS_FREE(symbols); } mxs_log_flush_sync(); @@ -434,8 +433,6 @@ sigfatal_handler(int i) raise(i); } - - /** * @node Wraps sigaction calls *