#include <folly/debugging/exception_tracer/ExceptionTracerLib.h>
#include <folly/debugging/exception_tracer/SmartExceptionTracerSingleton.h>
#include <folly/experimental/symbolizer/Symbolizer.h>
#if FOLLY_HAVE_ELF && FOLLY_HAVE_DWARF
#if defined(__GLIBCXX__)
namespace folly::exception_tracer {
namespace {
void metaDeleter(void* ex) noexcept {
auto syncMeta = detail::getMetaMap().withWLock([ex](auto& locked) noexcept {
auto iter = locked.find(ex);
auto ret = std::move(iter->second);
locked.erase(iter);
return ret;
});
auto meta = syncMeta->wlock();
if (meta->deleter) {
meta->deleter(ex);
}
}
void throwCallback(
void* ex, std::type_info*, void (**deleter)(void*)) noexcept {
static thread_local bool handlingThrow;
if (handlingThrow) {
return;
}
SCOPE_EXIT {
handlingThrow = false;
};
handlingThrow = true;
try {
auto newMeta = std::make_unique<detail::SynchronizedExceptionMeta>();
newMeta->withWLock([&deleter](auto& lockedMeta) {
lockedMeta.deleter = std::exchange(*deleter, metaDeleter);
ssize_t n = folly::symbolizer::getStackTrace(
lockedMeta.trace.addresses, kMaxFrames);
if (n != -1) {
lockedMeta.trace.frameCount = n;
}
ssize_t nAsync = folly::symbolizer::getAsyncStackTraceSafe(
lockedMeta.traceAsync.addresses, kMaxFrames);
if (nAsync != -1) {
lockedMeta.traceAsync.frameCount = nAsync;
}
});
auto oldMeta = detail::getMetaMap().withWLock([ex, &newMeta](auto& wlock) {
return std::exchange(wlock[ex], std::move(newMeta));
});
DCHECK(oldMeta == nullptr);
} catch (const std::bad_alloc&) {
}
}
struct Initialize {
Initialize() {
registerCxaThrowCallback(throwCallback);
detail::setSmartExceptionTracerHookEnabled(true);
}
};
Initialize initialize;
}
}
#endif
#endif