Take dump_stacktrace into use
MaxScale and tests now both use the same code to dump stacktraces.
This commit is contained in:
@ -92,7 +92,7 @@ if (HAVE_LIBDL)
|
||||
target_link_libraries(maxscale-common dl)
|
||||
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")
|
||||
install_module(maxscale-common core)
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <maxbase/stacktrace.hh>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/adminusers.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));
|
||||
|
||||
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
|
||||
sigfatal_handler(int i)
|
||||
{
|
||||
@ -487,33 +398,18 @@ sigfatal_handler(int i)
|
||||
"Attempting backtrace.\n", i);
|
||||
fprintf(stderr, "Commit ID: %s System name: %s Release string: %s\n\n",
|
||||
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. "
|
||||
"Attempting backtrace.", i);
|
||||
MXS_ALERT("Commit ID: %s System name: %s "
|
||||
"Release string: %s",
|
||||
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)
|
||||
auto cb = [](const char* symbol, const char* cmd)
|
||||
{
|
||||
for (int n = 0; n < count; n++)
|
||||
{
|
||||
char cmd[PATH_MAX + 1024] = "<not found>";
|
||||
extract_file_and_line(symbols[n], cmd, sizeof(cmd));
|
||||
MXS_ALERT(" %s: %s", symbols[n], cmd);
|
||||
}
|
||||
MXS_FREE(symbols);
|
||||
}
|
||||
#endif
|
||||
MXS_ALERT(" %s: %s", symbol, cmd);
|
||||
};
|
||||
|
||||
mxb::dump_stacktrace(cb);
|
||||
|
||||
mxs_log_flush_sync();
|
||||
|
||||
|
Reference in New Issue
Block a user