WIP: Fancy backtrace interface
parent
a27b359aa7
commit
ad73a0f098
|
@ -137,6 +137,7 @@ static void log_backtrace(void* const *trace, int trace_size, const ss_ &title)
|
||||||
// The first stack frame points to this functiton
|
// The first stack frame points to this functiton
|
||||||
backtrace_buffer_len = 0;
|
backtrace_buffer_len = 0;
|
||||||
bt_print("\n %s", cs(title));
|
bt_print("\n %s", cs(title));
|
||||||
|
int first_real_i = 1;
|
||||||
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
|
||||||
|
@ -164,11 +165,20 @@ static void log_backtrace(void* const *trace, int trace_size, const ss_ &title)
|
||||||
address, cs(file_path));
|
address, cs(file_path));
|
||||||
ss_ addr2line_output = exec_get_stdout_without_newline(cmdbuf);
|
ss_ addr2line_output = exec_get_stdout_without_newline(cmdbuf);
|
||||||
|
|
||||||
|
// Clean up the beginning of the backtrace (for whatever reason there
|
||||||
|
// often seems to be two basic_string-related lines at the beginnong of
|
||||||
|
// the backtrace)
|
||||||
|
if(i <= 2 && i <= first_real_i &&
|
||||||
|
addr2line_output.find("/basic_string.h") != ss_::npos){
|
||||||
|
first_real_i = i + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(addr2line_output.size() > 4){
|
if(addr2line_output.size() > 4){
|
||||||
bt_print(" #%i %s", i-1, cs(addr2line_output));
|
bt_print(" #%i %s", i-first_real_i, cs(addr2line_output));
|
||||||
log_d(MODULE, " = %s", cs(cppfilt_symbol));
|
log_d(MODULE, " = %s", cs(cppfilt_symbol));
|
||||||
} else {
|
} else {
|
||||||
bt_print(" #%i %s", i-1, cs(cppfilt_symbol));
|
bt_print(" #%i %s", i-first_real_i, cs(cppfilt_symbol));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +234,26 @@ void log_exception_backtrace(const ss_ &title)
|
||||||
log_backtrace(last_exception_frames, last_exception_num_frames, title);
|
log_backtrace(last_exception_frames, last_exception_num_frames, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_current_backtrace(StoredBacktrace &result)
|
||||||
|
{
|
||||||
|
result.exception_name.clear();
|
||||||
|
result.num_frames = backtrace(result.frames, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_exception_backtrace(StoredBacktrace &result)
|
||||||
|
{
|
||||||
|
result.exception_name = last_exception_name;
|
||||||
|
result.num_frames = last_exception_num_frames;
|
||||||
|
for(int i = 0; i < result.num_frames; i++){
|
||||||
|
result.frames[i] = last_exception_frames[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_backtrace(const StoredBacktrace &result, const ss_ &title)
|
||||||
|
{
|
||||||
|
log_backtrace(result.frames, result.num_frames, title);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vim: set noet ts=4 sw=4:
|
// vim: set noet ts=4 sw=4:
|
||||||
|
|
|
@ -22,6 +22,18 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_current_backtrace(StoredBacktrace &result)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_exception_backtrace(StoredBacktrace &result)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_backtrace(const StoredBacktrace &result, const ss_ &title)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vim: set noet ts=4 sw=4:
|
// vim: set noet ts=4 sw=4:
|
||||||
|
|
|
@ -15,8 +15,19 @@ namespace interface
|
||||||
void init_signal_handlers(const SigConfig &config);
|
void init_signal_handlers(const SigConfig &config);
|
||||||
|
|
||||||
void log_current_backtrace(const ss_ &title="Current backtrace:");
|
void log_current_backtrace(const ss_ &title="Current backtrace:");
|
||||||
|
|
||||||
void log_exception_backtrace(const ss_ &title="Exception backtrace:");
|
void log_exception_backtrace(const ss_ &title="Exception backtrace:");
|
||||||
|
|
||||||
|
struct StoredBacktrace {
|
||||||
|
void *frames[16];
|
||||||
|
int num_frames = 0;
|
||||||
|
ss_ exception_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
void get_current_backtrace(StoredBacktrace &result);
|
||||||
|
void get_exception_backtrace(StoredBacktrace &result);
|
||||||
|
|
||||||
|
void log_backtrace(const StoredBacktrace &result,
|
||||||
|
const ss_ &title="Stored backtrace:");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vim: set noet ts=4 sw=4:
|
// vim: set noet ts=4 sw=4:
|
||||||
|
|
|
@ -103,10 +103,14 @@ struct ModuleContainer
|
||||||
thread->start();
|
thread->start();
|
||||||
}
|
}
|
||||||
// Initialize in thread
|
// Initialize in thread
|
||||||
|
std::exception_ptr eptr;
|
||||||
bool ok = execute_direct_cb([&](interface::Module *module){
|
bool ok = execute_direct_cb([&](interface::Module *module){
|
||||||
module->init();
|
module->init();
|
||||||
});
|
}, eptr);
|
||||||
(void)ok; // Ignored; fails generally on SIGINT at statup
|
(void)ok; // Ignored; fails generally on SIGINT at statup
|
||||||
|
if(eptr){
|
||||||
|
std::rethrow_exception(eptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void thread_request_stop(){
|
void thread_request_stop(){
|
||||||
interface::MutexScope ms(mutex);
|
interface::MutexScope ms(mutex);
|
||||||
|
@ -152,7 +156,8 @@ struct ModuleContainer
|
||||||
module->event(event.type, event.p.get());
|
module->event(event.type, event.p.get());
|
||||||
}
|
}
|
||||||
// If returns false, the module thread is stopping and cannot be called
|
// If returns false, the module thread is stopping and cannot be called
|
||||||
bool execute_direct_cb(const std::function<void(interface::Module*)> &cb){
|
bool execute_direct_cb(const std::function<void(interface::Module*)> &cb,
|
||||||
|
std::exception_ptr &result_exception){
|
||||||
log_t(MODULE, "execute_direct_cb[%s]: Waiting for direct_cb to be free",
|
log_t(MODULE, "execute_direct_cb[%s]: Waiting for direct_cb to be free",
|
||||||
cs(info.name));
|
cs(info.name));
|
||||||
direct_cb_free_sem.wait(); // Wait for direct_cb to be free
|
direct_cb_free_sem.wait(); // Wait for direct_cb to be free
|
||||||
|
@ -195,12 +200,16 @@ struct ModuleContainer
|
||||||
" exception", cs(info.name));
|
" exception", cs(info.name));
|
||||||
/*interface::debug::log_current_backtrace(
|
/*interface::debug::log_current_backtrace(
|
||||||
"Backtrace for M["+info.name+"]'s caller:");*/
|
"Backtrace for M["+info.name+"]'s caller:");*/
|
||||||
std::rethrow_exception(eptr);
|
interface::debug::StoredBacktrace bt;
|
||||||
|
interface::debug::get_current_backtrace(bt);
|
||||||
|
interface::debug::log_backtrace(bt,
|
||||||
|
"Backtrace for M["+info.name+"]'s caller:");
|
||||||
|
result_exception = eptr;
|
||||||
} else {
|
} else {
|
||||||
log_t(MODULE, "execute_direct_cb[%s]: Execution finished",
|
log_t(MODULE, "execute_direct_cb[%s]: Execution finished",
|
||||||
cs(info.name));
|
cs(info.name));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -966,13 +975,12 @@ struct CState: public State, public interface::Server
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute callback in module thread
|
// Execute callback in module thread
|
||||||
bool ok = mc->execute_direct_cb(cb);
|
std::exception_ptr eptr;
|
||||||
|
bool ok = mc->execute_direct_cb(cb, eptr);
|
||||||
(void)ok; // Unused
|
(void)ok; // Unused
|
||||||
/*if(!ok && !caller_module_name.empty()){
|
if(eptr){
|
||||||
throw interface::TargetModuleStopped("access_module(): Module \""+
|
std::rethrow_exception(eptr);
|
||||||
module_name+"\" is stopping (called by \""+
|
}
|
||||||
caller_module_name+"\")");
|
|
||||||
}*/
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue