Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] stack trace printing in signal handlers #630

Open
szha opened this issue Aug 16, 2020 · 0 comments
Open

[Feature] stack trace printing in signal handlers #630

szha opened this issue Aug 16, 2020 · 0 comments

Comments

@szha
Copy link
Member

szha commented Aug 16, 2020

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.

@szha szha changed the title [Feature] stack trace printing [Feature] stack trace printing in signal handlers Aug 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant