Skip to content

[Feature] stack trace printing in signal handlers #630

@szha

Description

@szha

Currently in DMLC core the utility for printing stacktrace (and demangling) are the following:

inline std::string Demangle(char const *msg_str) {
using std::string;
string msg(msg_str);
size_t symbol_start = string::npos;
size_t symbol_end = string::npos;
if ( ((symbol_start = msg.find("_Z")) != string::npos)
&& (symbol_end = msg.find_first_of(" +", symbol_start)) ) {
string left_of_symbol(msg, 0, symbol_start);
string symbol(msg, symbol_start, symbol_end - symbol_start);
string right_of_symbol(msg, symbol_end);
int status = 0;
size_t length = string::npos;
std::unique_ptr<char, void (*)(void *__ptr)> demangled_symbol =
{abi::__cxa_demangle(symbol.c_str(), 0, &length, &status), &std::free};
if (demangled_symbol && status == 0 && length > 0) {
string symbol_str(demangled_symbol.get());
std::ostringstream os;
os << left_of_symbol << symbol_str << right_of_symbol;
return os.str();
}
}
return string(msg_str);
}
// By default skip the first frame because
// that belongs to ~LogMessageFatal
inline std::string StackTrace(
size_t start_frame = 1,
const size_t stack_size = DMLC_LOG_STACK_TRACE_SIZE) {
using std::string;
std::ostringstream stacktrace_os;
std::vector<void*> stack(stack_size);
int nframes = backtrace(stack.data(), static_cast<int>(stack_size));
if (start_frame < static_cast<size_t>(nframes)) {
stacktrace_os << "Stack trace:\n";
}
char **msgs = backtrace_symbols(stack.data(), nframes);
if (msgs != nullptr) {
for (int frameno = start_frame; frameno < nframes; ++frameno) {
string msg = dmlc::Demangle(msgs[frameno]);
stacktrace_os << " [bt] (" << frameno - start_frame << ") " << msg << "\n";
}
}
free(msgs);
string stack_trace = stacktrace_os.str();
return stack_trace;
}

The problem with them is that they can't be used safely in asynchronous signal handlers, for which non-reentrant functions are required.

According to boost, there isn't a safe way to get stacktrace that's portable. On the other hand, one was described in this blog. The downside is that on windows it relies on StackWalker. There may be better, more modern ways to achieve this that I missed.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions