SignalSafeElfCache signalSafeElfCache(kDefaultCapacity);
} // namespace
-void dumpStackTrace() __attribute__((noinline));
+void dumpStackTrace(bool symbolize) __attribute__((noinline));
-void dumpStackTrace() {
+void dumpStackTrace(bool symbolize) {
SCOPE_EXIT { fsyncNoInt(STDERR_FILENO); };
// Get and symbolize stack trace
constexpr size_t kMaxStackTraceDepth = 100;
// Skip the getStackTrace frame
if (!getStackTraceSafe(addresses)) {
print("(error retrieving stack trace)\n");
- } else {
+ } else if (symbolize) {
Symbolizer symbolizer(&signalSafeElfCache);
symbolizer.symbolize(addresses);
//
// Leaving signalHandler on the stack for clarity, I think.
printer.println(addresses, 2);
+ } else {
+ print("(safe mode, symbolizer not available)\n");
+ AddressFormatter formatter;
+ for (ssize_t i = 0; i < addresses.frameCount; ++i) {
+ print(formatter.format(addresses.addresses[i]));
+ print("\n");
+ }
}
}
constexpr pthread_t kInvalidThreadId = 0;
std::atomic<pthread_t> gSignalThread(kInvalidThreadId);
+std::atomic<bool> gInRecursiveSignalHandler(false);
// Here be dragons.
void innerSignalHandler(int signum, siginfo_t* info, void* uctx) {
pthread_t prevSignalThread = kInvalidThreadId;
while (!gSignalThread.compare_exchange_strong(prevSignalThread, myId)) {
if (pthread_equal(prevSignalThread, myId)) {
- print("Entered fatal signal handler recursively. We're in trouble.\n");
+ // First time here. Try to dump the stack trace without symbolization.
+ // If we still fail, well, we're mightily screwed, so we do nothing the
+ // next time around.
+ if (!gInRecursiveSignalHandler.exchange(true)) {
+ print("Entered fatal signal handler recursively. We're in trouble.\n");
+ dumpStackTrace(false); // no symbolization
+ }
return;
}
dumpTimeInfo();
dumpSignalInfo(signum, info);
- dumpStackTrace();
+ dumpStackTrace(true); // with symbolization
// Run user callbacks
gFatalSignalCallbackRegistry->run();
const SymbolizePrinter::Color kFileColor = SymbolizePrinter::Color::DEFAULT;
} // namespace
+constexpr char AddressFormatter::bufTemplate[];
+
+AddressFormatter::AddressFormatter() {
+ memcpy(buf_, bufTemplate, sizeof(buf_));
+}
+
+folly::StringPiece AddressFormatter::format(uintptr_t address) {
+ // Can't use sprintf, not async-signal-safe
+ static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
+ char* end = buf_ + sizeof(buf_) - 1 - (16 - 2 * sizeof(uintptr_t));
+ char* p = end;
+ *p-- = '\0';
+ while (address != 0) {
+ *p-- = kHexChars[address & 0xf];
+ address >>= 4;
+ }
+
+ return folly::StringPiece(buf_, end);
+}
+
void SymbolizePrinter::print(uintptr_t address, const SymbolizedFrame& frame) {
if (options_ & TERSE) {
printTerse(address, frame);
SCOPE_EXIT { color(Color::DEFAULT); };
color(kAddressColor);
- // Can't use sprintf, not async-signal-safe
- static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
- char buf[] = " @ 0000000000000000";
- char* end = buf + sizeof(buf) - 1 - (16 - 2 * sizeof(uintptr_t));
+
+ AddressFormatter formatter;
+ doPrint(formatter.format(address));
+
const char padBuf[] = " ";
folly::StringPiece pad(padBuf,
sizeof(padBuf) - 1 - (16 - 2 * sizeof(uintptr_t)));
- char* p = end;
- *p-- = '\0';
- while (address != 0) {
- *p-- = kHexChars[address & 0xf];
- address >>= 4;
- }
- doPrint(folly::StringPiece(buf, end));
color(kFunctionColor);
char mangledBuf[1024];