server, debug: Fancier backtraces

This commit is contained in:
Perttu Ahola 2014-10-30 04:08:15 +02:00
parent 0577f619d2
commit 2fa5d016d1
5 changed files with 45 additions and 16 deletions

View File

@ -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);
} }
} }

View File

@ -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));

View File

@ -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");
} }

View File

@ -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:

View File

@ -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());
} }