server, debug: Fancier backtraces
This commit is contained in:
parent
0577f619d2
commit
2fa5d016d1
@ -8,6 +8,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cstdarg>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/ucontext.h>
|
#include <sys/ucontext.h>
|
||||||
@ -67,7 +68,7 @@ static void* get_library_executable_address(const ss_ &lib_path)
|
|||||||
#define REG_EIP REG_RIP
|
#define REG_EIP REG_RIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void log_backtrace(void* const *trace, int trace_size);
|
static void log_backtrace(void* const *trace, int trace_size, const ss_ &title);
|
||||||
|
|
||||||
static void debug_sighandler(int sig, siginfo_t *info, void *secret)
|
static void debug_sighandler(int sig, siginfo_t *info, void *secret)
|
||||||
{
|
{
|
||||||
@ -84,7 +85,7 @@ static void debug_sighandler(int sig, siginfo_t *info, void *secret)
|
|||||||
// Overwrite sigaction with caller's address
|
// Overwrite sigaction with caller's address
|
||||||
trace[1] = (void*) uc->uc_mcontext.gregs[REG_EIP];
|
trace[1] = (void*) uc->uc_mcontext.gregs[REG_EIP];
|
||||||
|
|
||||||
log_backtrace(trace, trace_size);
|
log_backtrace(trace, trace_size, "Backtrace for signal:");
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -103,8 +104,25 @@ void init_signal_handlers(const SigConfig &config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::atomic_int log_backtrace_spinlock(0);
|
static std::atomic_int log_backtrace_spinlock(0);
|
||||||
|
static char backtrace_buffer[10000];
|
||||||
|
static size_t backtrace_buffer_len = 0;
|
||||||
|
|
||||||
static void log_backtrace(void* const *trace, int trace_size)
|
static void bt_print(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va_args;
|
||||||
|
va_start(va_args, fmt);
|
||||||
|
backtrace_buffer_len += vsnprintf(
|
||||||
|
backtrace_buffer + backtrace_buffer_len,
|
||||||
|
sizeof backtrace_buffer - backtrace_buffer_len,
|
||||||
|
fmt, va_args);
|
||||||
|
va_end(va_args);
|
||||||
|
backtrace_buffer_len += snprintf(
|
||||||
|
backtrace_buffer + backtrace_buffer_len,
|
||||||
|
sizeof backtrace_buffer - backtrace_buffer_len,
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_backtrace(void* const *trace, int trace_size, const ss_ &title)
|
||||||
{
|
{
|
||||||
char **symbols = backtrace_symbols(trace, trace_size);
|
char **symbols = backtrace_symbols(trace, trace_size);
|
||||||
|
|
||||||
@ -117,7 +135,8 @@ static void log_backtrace(void* const *trace, int trace_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The first stack frame points to this functiton
|
// The first stack frame points to this functiton
|
||||||
log_i(MODULE, "Backtrace:");
|
backtrace_buffer_len = 0;
|
||||||
|
bt_print("\n %s", cs(title));
|
||||||
for(int i = 1; i < trace_size; i++){
|
for(int i = 1; i < trace_size; i++){
|
||||||
char cmdbuf[500];
|
char cmdbuf[500];
|
||||||
// Parse symbol to get file name
|
// Parse symbol to get file name
|
||||||
@ -146,23 +165,27 @@ static void log_backtrace(void* const *trace, int trace_size)
|
|||||||
ss_ addr2line_output = exec_get_stdout_without_newline(cmdbuf);
|
ss_ addr2line_output = exec_get_stdout_without_newline(cmdbuf);
|
||||||
|
|
||||||
if(addr2line_output.size() > 4){
|
if(addr2line_output.size() > 4){
|
||||||
log_i(MODULE, "#%i %s", i-1, cs(addr2line_output));
|
bt_print(" #%i %s", i-1, cs(addr2line_output));
|
||||||
log_d(MODULE, " = %s", cs(cppfilt_symbol));
|
log_d(MODULE, " = %s", cs(cppfilt_symbol));
|
||||||
} else {
|
} else {
|
||||||
log_i(MODULE, "#%i %s", i-1, cs(cppfilt_symbol));
|
bt_print(" #%i %s", i-1, cs(cppfilt_symbol));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print to log
|
||||||
|
backtrace_buffer[sizeof backtrace_buffer - 1] = 0;
|
||||||
|
log_i(MODULE, "%s", backtrace_buffer);
|
||||||
|
|
||||||
// Unlock spinlock
|
// Unlock spinlock
|
||||||
log_backtrace_spinlock--;
|
log_backtrace_spinlock--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_current_backtrace()
|
void log_current_backtrace(const ss_ &title)
|
||||||
{
|
{
|
||||||
void *trace[16];
|
void *trace[16];
|
||||||
int trace_size = backtrace(trace, 16);
|
int trace_size = backtrace(trace, 16);
|
||||||
|
|
||||||
log_backtrace(trace, trace_size);
|
log_backtrace(trace, trace_size, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
@ -196,9 +219,9 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_exception_backtrace()
|
void log_exception_backtrace(const ss_ &title)
|
||||||
{
|
{
|
||||||
log_backtrace(last_exception_frames, last_exception_num_frames);
|
log_backtrace(last_exception_frames, last_exception_num_frames, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,10 @@ struct CThread: public Thread
|
|||||||
} catch(std::exception &e){
|
} catch(std::exception &e){
|
||||||
log_w(MODULE, "ThreadThing of thread %p (%s) failed: %s",
|
log_w(MODULE, "ThreadThing of thread %p (%s) failed: %s",
|
||||||
arg, cs(thread_name), e.what());
|
arg, cs(thread_name), e.what());
|
||||||
interface::debug::log_exception_backtrace();
|
interface::debug::log_exception_backtrace(
|
||||||
|
"Backtrace for ThreadThing("+thread_name+"):");
|
||||||
|
/*interface::debug::log_current_backtrace(
|
||||||
|
"Backtrace for ThreadThing("+thread_name+") (current):");*/
|
||||||
}
|
}
|
||||||
|
|
||||||
log_d(MODULE, "Thread %p (%s) exit", arg, cs(thread_name));
|
log_d(MODULE, "Thread %p (%s) exit", arg, cs(thread_name));
|
||||||
|
@ -12,12 +12,12 @@ void init_signal_handlers(const SigConfig &config)
|
|||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_current_backtrace()
|
void log_current_backtrace(const ss_ &title)
|
||||||
{
|
{
|
||||||
log_i(MODULE, "Backtrace logging not implemented on Windows");
|
log_i(MODULE, "Backtrace logging not implemented on Windows");
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_exception_backtrace()
|
void log_exception_backtrace(const ss_ &title)
|
||||||
{
|
{
|
||||||
log_i(MODULE, "Backtrace logging not implemented on Windows");
|
log_i(MODULE, "Backtrace logging not implemented on Windows");
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ namespace interface
|
|||||||
|
|
||||||
void init_signal_handlers(const SigConfig &config);
|
void init_signal_handlers(const SigConfig &config);
|
||||||
|
|
||||||
void log_current_backtrace();
|
void log_current_backtrace(const ss_ &title="Current backtrace:");
|
||||||
|
|
||||||
void log_exception_backtrace();
|
void log_exception_backtrace(const ss_ &title="Exception backtrace:");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vim: set noet ts=4 sw=4:
|
// vim: set noet ts=4 sw=4:
|
||||||
|
@ -193,6 +193,8 @@ struct ModuleContainer
|
|||||||
if(eptr){
|
if(eptr){
|
||||||
log_t(MODULE, "execute_direct_cb[%s]: Execution finished by"
|
log_t(MODULE, "execute_direct_cb[%s]: Execution finished by"
|
||||||
" exception", cs(info.name));
|
" exception", cs(info.name));
|
||||||
|
/*interface::debug::log_current_backtrace(
|
||||||
|
"Backtrace for M["+info.name+"]'s caller:");*/
|
||||||
std::rethrow_exception(eptr);
|
std::rethrow_exception(eptr);
|
||||||
} else {
|
} else {
|
||||||
log_t(MODULE, "execute_direct_cb[%s]: Execution finished",
|
log_t(MODULE, "execute_direct_cb[%s]: Execution finished",
|
||||||
@ -290,7 +292,8 @@ void ModuleThread::run(interface::Thread *thread)
|
|||||||
cs(mc->info.name), e.what());
|
cs(mc->info.name), e.what());
|
||||||
// If event handling results in an uncatched exception, the
|
// If event handling results in an uncatched exception, the
|
||||||
// server shall shut down.
|
// server shall shut down.
|
||||||
interface::debug::log_exception_backtrace();
|
interface::debug::log_exception_backtrace(
|
||||||
|
"Backtrace for M["+mc->info.name+"]->event():");
|
||||||
mc->server->shutdown(1, "M["+mc->info.name+"]->event() "
|
mc->server->shutdown(1, "M["+mc->info.name+"]->event() "
|
||||||
"failed: "+e.what());
|
"failed: "+e.what());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user