Commit c2281fce authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook Github Bot

Expose active exceptions stack in ExceptionStackTraceLib

Summary: It can be useful for diagnostics to print the stack traces of thrown exceptions that are not yet handled, for example if a fatal error happens during unwinding.

Reviewed By: philippv, luciang

Differential Revision: D19191089

fbshipit-source-id: dae8cc0a095570bfe7d6c4c7ef2b5dc08aa9f1f9
parent f519c88f
...@@ -30,13 +30,16 @@ namespace { ...@@ -30,13 +30,16 @@ namespace {
// trace at all because in could be bogus // trace at all because in could be bogus
FOLLY_TLS bool invalid; FOLLY_TLS bool invalid;
FOLLY_TLS StackTraceStack activeExceptions; FOLLY_TLS StackTraceStack uncaughtExceptions;
FOLLY_TLS StackTraceStack caughtExceptions; FOLLY_TLS StackTraceStack caughtExceptions;
} // namespace } // namespace
// This function is exported and may be found via dlsym(RTLD_NEXT, ...) // These functions are exported and may be found via dlsym(RTLD_NEXT, ...)
extern "C" StackTraceStack* getExceptionStackTraceStack() { extern "C" StackTraceStack* getUncaughtExceptionStackTraceStack() {
return invalid ? nullptr : &uncaughtExceptions;
}
extern "C" StackTraceStack* getCaughtExceptionStackTraceStack() {
return invalid ? nullptr : &caughtExceptions; return invalid ? nullptr : &caughtExceptions;
} }
...@@ -45,8 +48,8 @@ namespace { ...@@ -45,8 +48,8 @@ namespace {
void addActiveException() { void addActiveException() {
// Capture stack trace // Capture stack trace
if (!invalid) { if (!invalid) {
if (!activeExceptions.pushCurrent()) { if (!uncaughtExceptions.pushCurrent()) {
activeExceptions.clear(); uncaughtExceptions.clear();
caughtExceptions.clear(); caughtExceptions.clear();
invalid = true; invalid = true;
} }
...@@ -72,11 +75,11 @@ struct Initializer { ...@@ -72,11 +75,11 @@ struct Initializer {
}); });
registerCxaBeginCatchCallback([](void*) noexcept { registerCxaBeginCatchCallback([](void*) noexcept {
moveTopException(activeExceptions, caughtExceptions); moveTopException(uncaughtExceptions, caughtExceptions);
}); });
registerCxaRethrowCallback([]() noexcept { registerCxaRethrowCallback([]() noexcept {
moveTopException(caughtExceptions, activeExceptions); moveTopException(caughtExceptions, uncaughtExceptions);
}); });
registerCxaEndCatchCallback([]() noexcept { registerCxaEndCatchCallback([]() noexcept {
...@@ -95,7 +98,7 @@ struct Initializer { ...@@ -95,7 +98,7 @@ struct Initializer {
// For Lua interop, we see the handlerCount = 0 // For Lua interop, we see the handlerCount = 0
if ((top->handlerCount == 1) || (top->handlerCount == 0)) { if ((top->handlerCount == 1) || (top->handlerCount == 0)) {
if (!caughtExceptions.pop()) { if (!caughtExceptions.pop()) {
activeExceptions.clear(); uncaughtExceptions.clear();
invalid = true; invalid = true;
} }
} }
......
...@@ -37,9 +37,10 @@ using namespace ::folly::symbolizer; ...@@ -37,9 +37,10 @@ using namespace ::folly::symbolizer;
using namespace __cxxabiv1; using namespace __cxxabiv1;
extern "C" { extern "C" {
StackTraceStack* getExceptionStackTraceStack(void) __attribute__((__weak__)); StackTraceStack* getCaughtExceptionStackTraceStack(void)
typedef StackTraceStack* (*GetExceptionStackTraceStackType)(); __attribute__((__weak__));
GetExceptionStackTraceStackType getExceptionStackTraceStackFn; typedef StackTraceStack* (*GetCaughtExceptionStackTraceStackType)();
GetCaughtExceptionStackTraceStackType getCaughtExceptionStackTraceStackFn;
} }
} // namespace } // namespace
...@@ -130,13 +131,14 @@ bool isAbiCppException(const __cxa_exception* exc) { ...@@ -130,13 +131,14 @@ bool isAbiCppException(const __cxa_exception* exc) {
std::vector<ExceptionInfo> getCurrentExceptions() { std::vector<ExceptionInfo> getCurrentExceptions() {
struct Once { struct Once {
Once() { Once() {
// See if linked in with us (getExceptionStackTraceStack is weak) // See if linked in with us (getCaughtExceptionStackTraceStack is weak)
getExceptionStackTraceStackFn = getExceptionStackTraceStack; getCaughtExceptionStackTraceStackFn = getCaughtExceptionStackTraceStack;
if (!getExceptionStackTraceStackFn) { if (!getCaughtExceptionStackTraceStackFn) {
// Nope, see if it's in a shared library // Nope, see if it's in a shared library
getExceptionStackTraceStackFn = (GetExceptionStackTraceStackType)dlsym( getCaughtExceptionStackTraceStackFn =
RTLD_NEXT, "getExceptionStackTraceStack"); (GetCaughtExceptionStackTraceStackType)dlsym(
RTLD_NEXT, "getCaughtExceptionStackTraceStack");
} }
} }
}; };
...@@ -149,14 +151,14 @@ std::vector<ExceptionInfo> getCurrentExceptions() { ...@@ -149,14 +151,14 @@ std::vector<ExceptionInfo> getCurrentExceptions() {
} }
StackTraceStack* traceStack = nullptr; StackTraceStack* traceStack = nullptr;
if (!getExceptionStackTraceStackFn) { if (!getCaughtExceptionStackTraceStackFn) {
static bool logged = false; static bool logged = false;
if (!logged) { if (!logged) {
LOG(WARNING) LOG(WARNING)
<< "Exception tracer library not linked, stack traces not available"; << "Exception tracer library not linked, stack traces not available";
logged = true; logged = true;
} }
} else if ((traceStack = getExceptionStackTraceStackFn()) == nullptr) { } else if ((traceStack = getCaughtExceptionStackTraceStackFn()) == nullptr) {
static bool logged = false; static bool logged = false;
if (!logged) { if (!logged) {
LOG(WARNING) LOG(WARNING)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment