X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fexperimental%2Fsymbolizer%2FSignalHandler.cpp;h=02e5ef05219c58fa43d6c7fb3f8c81f40c63fa47;hp=8346e79bea31ff5420882b64d993033951ce030d;hb=af7e70660f867873638ef2ce5bb33b19771bdd41;hpb=3aed59d8e656abb09c33102f7a7caf45cf06155d diff --git a/folly/experimental/symbolizer/SignalHandler.cpp b/folly/experimental/symbolizer/SignalHandler.cpp index 8346e79b..02e5ef05 100644 --- a/folly/experimental/symbolizer/SignalHandler.cpp +++ b/folly/experimental/symbolizer/SignalHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -188,21 +188,44 @@ void dumpSignalInfo(int signum, siginfo_t* siginfo) { print("), stack trace: ***\n"); } -void dumpStackTrace() { +namespace { +constexpr size_t kDefaultCapacity = 500; + +// Note: not thread-safe, but that's okay, as we only let one thread +// in our signal handler at a time. +SignalSafeElfCache signalSafeElfCache(kDefaultCapacity); +} // namespace + +void dumpStackTrace(bool symbolize) __attribute__((noinline)); + +void dumpStackTrace(bool symbolize) { SCOPE_EXIT { fsyncNoInt(STDERR_FILENO); }; // Get and symbolize stack trace constexpr size_t kMaxStackTraceDepth = 100; FrameArray addresses; // Skip the getStackTrace frame - if (!getStackTrace(addresses)) { + if (!getStackTraceSafe(addresses)) { print("(error retrieving stack trace)\n"); - } else { - Symbolizer symbolizer; + } else if (symbolize) { + Symbolizer symbolizer(&signalSafeElfCache); symbolizer.symbolize(addresses); - FDSymbolizePrinter printer(STDERR_FILENO); - printer.println(addresses); + FDSymbolizePrinter printer(STDERR_FILENO, SymbolizePrinter::COLOR_IF_TTY); + + // Skip the top 2 frames: + // getStackTraceSafe + // dumpStackTrace (here) + // + // 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"); + } } } @@ -213,6 +236,7 @@ void dumpStackTrace() { constexpr pthread_t kInvalidThreadId = 0; std::atomic gSignalThread(kInvalidThreadId); +std::atomic gInRecursiveSignalHandler(false); // Here be dragons. void innerSignalHandler(int signum, siginfo_t* info, void* uctx) { @@ -222,7 +246,13 @@ 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; } @@ -237,7 +267,7 @@ void innerSignalHandler(int signum, siginfo_t* info, void* uctx) { dumpTimeInfo(); dumpSignalInfo(signum, info); - dumpStackTrace(); + dumpStackTrace(true); // with symbolization // Run user callbacks gFatalSignalCallbackRegistry->run(); @@ -286,4 +316,3 @@ void installFatalSignalHandler() { } }} // namespaces -