Take dump_stacktrace into use
MaxScale and tests now both use the same code to dump stacktraces.
This commit is contained in:
@ -8,12 +8,15 @@
|
|||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <maxbase/stacktrace.hh>
|
||||||
|
|
||||||
#include "mariadb_func.h"
|
#include "mariadb_func.h"
|
||||||
#include "maxadmin_operations.h"
|
#include "maxadmin_operations.h"
|
||||||
#include "sql_t1.h"
|
#include "sql_t1.h"
|
||||||
#include "testconnections.h"
|
#include "testconnections.h"
|
||||||
|
|
||||||
|
using namespace mxb;
|
||||||
|
|
||||||
namespace maxscale
|
namespace maxscale
|
||||||
{
|
{
|
||||||
static bool start = true;
|
static bool start = true;
|
||||||
@ -37,9 +40,7 @@ static void signal_set(int sig, void (*handler)(int))
|
|||||||
|
|
||||||
void sigfatal_handler(int i)
|
void sigfatal_handler(int i)
|
||||||
{
|
{
|
||||||
void *addrs[128];
|
dump_stacktrace();
|
||||||
int count = backtrace(addrs, 128);
|
|
||||||
backtrace_symbols_fd(addrs, count, STDERR_FILENO);
|
|
||||||
signal_set(i, SIG_DFL);
|
signal_set(i, SIG_DFL);
|
||||||
raise(i);
|
raise(i);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ if (HAVE_LIBDL)
|
|||||||
target_link_libraries(maxscale-common dl)
|
target_link_libraries(maxscale-common dl)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_dependencies(maxscale-common pcre2 connector-c libmicrohttpd jansson)
|
add_dependencies(maxscale-common pcre2 connector-c libmicrohttpd jansson maxutils)
|
||||||
set_target_properties(maxscale-common PROPERTIES VERSION "1.0.0")
|
set_target_properties(maxscale-common PROPERTIES VERSION "1.0.0")
|
||||||
install_module(maxscale-common core)
|
install_module(maxscale-common core)
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <maxbase/stacktrace.hh>
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
#include <maxscale/adminusers.h>
|
#include <maxscale/adminusers.h>
|
||||||
#include <maxscale/dcb.h>
|
#include <maxscale/dcb.h>
|
||||||
@ -383,96 +384,6 @@ volatile sig_atomic_t fatal_handling = 0;
|
|||||||
|
|
||||||
static int signal_set(int sig, void (*handler)(int));
|
static int signal_set(int sig, void (*handler)(int));
|
||||||
|
|
||||||
void get_command_output(char* output, size_t size, const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list valist;
|
|
||||||
va_start(valist, format);
|
|
||||||
int cmd_len = vsnprintf(NULL, 0, format, valist);
|
|
||||||
va_end(valist);
|
|
||||||
|
|
||||||
va_start(valist, format);
|
|
||||||
char cmd[cmd_len + 1];
|
|
||||||
vsnprintf(cmd, cmd_len + 1, format, valist);
|
|
||||||
va_end(valist);
|
|
||||||
|
|
||||||
*output = '\0';
|
|
||||||
FILE* file = popen(cmd, "r");
|
|
||||||
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
size_t nread = fread(output, 1, size, file);
|
|
||||||
nread = nread < size ? nread : size - 1;
|
|
||||||
output[nread--] = '\0';
|
|
||||||
|
|
||||||
// Trim trailing newlines
|
|
||||||
while (output + nread > output && output[nread] == '\n')
|
|
||||||
{
|
|
||||||
output[nread--] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
pclose(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void extract_file_and_line(const char* symbols, char* cmd, size_t size)
|
|
||||||
{
|
|
||||||
const char* filename_end = strchr(symbols, '(');
|
|
||||||
const char* symname_end = strchr(symbols, ')');
|
|
||||||
|
|
||||||
if (filename_end && symname_end)
|
|
||||||
{
|
|
||||||
// This appears to be a symbol in a library
|
|
||||||
char filename[PATH_MAX + 1];
|
|
||||||
char symname[512];
|
|
||||||
char offset[512];
|
|
||||||
snprintf(filename, sizeof(filename), "%.*s", (int)(filename_end - symbols), symbols);
|
|
||||||
|
|
||||||
const char* symname_start = filename_end + 1;
|
|
||||||
|
|
||||||
if (*symname_start != '+')
|
|
||||||
{
|
|
||||||
// We have a string form symbol name and an offset, we need to
|
|
||||||
// extract the symbol address
|
|
||||||
|
|
||||||
const char* addr_offset = symname_start;
|
|
||||||
|
|
||||||
while (addr_offset < symname_end && *addr_offset != '+')
|
|
||||||
{
|
|
||||||
addr_offset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(symname, sizeof(symname), "%.*s", (int)(addr_offset - symname_start), symname_start);
|
|
||||||
|
|
||||||
if (addr_offset < symname_end && *addr_offset == '+')
|
|
||||||
{
|
|
||||||
addr_offset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(offset, sizeof(offset), "%.*s", (int)(symname_end - addr_offset), addr_offset);
|
|
||||||
|
|
||||||
// Get the hexadecimal address of the symbol
|
|
||||||
get_command_output(cmd, size,
|
|
||||||
"nm %s |grep ' %s$'|sed -e 's/ .*//' -e 's/^/0x/'",
|
|
||||||
filename, symname);
|
|
||||||
long long symaddr = strtoll(cmd, NULL, 16);
|
|
||||||
long long offsetaddr = strtoll(offset, NULL, 16);
|
|
||||||
|
|
||||||
// Calculate the file and line now that we have the raw offset into
|
|
||||||
// the library
|
|
||||||
get_command_output(cmd, size,
|
|
||||||
"addr2line -e %s 0x%x",
|
|
||||||
filename, symaddr + offsetaddr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Raw offset into library
|
|
||||||
symname_start++;
|
|
||||||
snprintf(symname, sizeof(symname), "%.*s", (int)(symname_end - symname_start), symname_start);
|
|
||||||
get_command_output(cmd, size, "addr2line -e %s %s", filename, symname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sigfatal_handler(int i)
|
sigfatal_handler(int i)
|
||||||
{
|
{
|
||||||
@ -487,33 +398,18 @@ sigfatal_handler(int i)
|
|||||||
"Attempting backtrace.\n", i);
|
"Attempting backtrace.\n", i);
|
||||||
fprintf(stderr, "Commit ID: %s System name: %s Release string: %s\n\n",
|
fprintf(stderr, "Commit ID: %s System name: %s Release string: %s\n\n",
|
||||||
maxscale_commit, cnf->sysname, cnf->release_string);
|
maxscale_commit, cnf->sysname, cnf->release_string);
|
||||||
#ifdef HAVE_GLIBC
|
|
||||||
|
|
||||||
void *addrs[128];
|
|
||||||
int count = backtrace(addrs, 128);
|
|
||||||
|
|
||||||
// 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. "
|
MXS_ALERT("Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. "
|
||||||
"Attempting backtrace.", i);
|
"Attempting backtrace.", i);
|
||||||
MXS_ALERT("Commit ID: %s System name: %s "
|
MXS_ALERT("Commit ID: %s System name: %s Release string: %s",
|
||||||
"Release string: %s",
|
|
||||||
maxscale_commit, cnf->sysname, cnf->release_string);
|
maxscale_commit, cnf->sysname, cnf->release_string);
|
||||||
// Then see if we can log them
|
|
||||||
char** symbols = backtrace_symbols(addrs, count);
|
|
||||||
|
|
||||||
if (symbols)
|
auto cb = [](const char* symbol, const char* cmd)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < count; n++)
|
MXS_ALERT(" %s: %s", symbol, cmd);
|
||||||
{
|
};
|
||||||
char cmd[PATH_MAX + 1024] = "<not found>";
|
|
||||||
extract_file_and_line(symbols[n], cmd, sizeof(cmd));
|
mxb::dump_stacktrace(cb);
|
||||||
MXS_ALERT(" %s: %s", symbols[n], cmd);
|
|
||||||
}
|
|
||||||
MXS_FREE(symbols);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mxs_log_flush_sync();
|
mxs_log_flush_sync();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user