Don't use recursion to print out the PrettyStackTrace after a crash. If the

crash was due to a stack overflow, chances are good that this would also cause
a stack overflow.

llvm-svn: 270903
This commit is contained in:
Richard Smith 2016-05-26 20:21:55 +00:00
parent f05c00c198
commit 978cfd3135
2 changed files with 35 additions and 19 deletions

View File

@ -29,9 +29,11 @@ namespace llvm {
/// constructed and destructed, they will add their symbolic frames to a /// constructed and destructed, they will add their symbolic frames to a
/// virtual stack trace. This gets dumped out if the program crashes. /// virtual stack trace. This gets dumped out if the program crashes.
class PrettyStackTraceEntry { class PrettyStackTraceEntry {
const PrettyStackTraceEntry *NextEntry; friend PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *);
PrettyStackTraceEntry *NextEntry;
PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete; PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete;
void operator=(const PrettyStackTraceEntry&) = delete; void operator=(const PrettyStackTraceEntry &) = delete;
public: public:
PrettyStackTraceEntry(); PrettyStackTraceEntry();
virtual ~PrettyStackTraceEntry(); virtual ~PrettyStackTraceEntry();
@ -67,7 +69,7 @@ namespace llvm {
}; };
/// Returns the topmost element of the "pretty" stack state. /// Returns the topmost element of the "pretty" stack state.
const void* SavePrettyStackState(); const void *SavePrettyStackState();
/// Restores the topmost element of the "pretty" stack state to State, which /// Restores the topmost element of the "pretty" stack state to State, which
/// should come from a previous call to SavePrettyStackState(). This is /// should come from a previous call to SavePrettyStackState(). This is
@ -76,7 +78,7 @@ namespace llvm {
/// happens after a crash that's been recovered by CrashRecoveryContext /// happens after a crash that's been recovered by CrashRecoveryContext
/// doesn't have frames on it that were added in code unwound by the /// doesn't have frames on it that were added in code unwound by the
/// CrashRecoveryContext. /// CrashRecoveryContext.
void RestorePrettyStackState(const void* State); void RestorePrettyStackState(const void *State);
} // end namespace llvm } // end namespace llvm

View File

@ -21,6 +21,8 @@
#include "llvm/Support/Watchdog.h" #include "llvm/Support/Watchdog.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <tuple>
#ifdef HAVE_CRASHREPORTERCLIENT_H #ifdef HAVE_CRASHREPORTERCLIENT_H
#include <CrashReporterClient.h> #include <CrashReporterClient.h>
#endif #endif
@ -36,20 +38,32 @@ using namespace llvm;
// objects, but we *really* cannot tolerate destructors running and do not want // objects, but we *really* cannot tolerate destructors running and do not want
// to pay any overhead of synchronizing. As a consequence, we use a raw // to pay any overhead of synchronizing. As a consequence, we use a raw
// thread-local variable. // thread-local variable.
static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead = static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
nullptr;
static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ namespace llvm {
unsigned NextID = 0; PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
if (Entry->getNextEntry()) PrettyStackTraceEntry *Prev = nullptr;
NextID = PrintStack(Entry->getNextEntry(), OS); while (Head)
OS << NextID << ".\t"; std::tie(Prev, Head, Head->NextEntry) =
{ std::make_tuple(Head, Head->NextEntry, Prev);
return Prev;
}
}
static void PrintStack(raw_ostream &OS) {
// Print out the stack in reverse order. To avoid recursion (which is likely
// to fail if we crashed due to stack overflow), we do an up-front pass to
// reverse the stack, then print it, then reverse it again.
unsigned ID = 0;
PrettyStackTraceEntry *ReversedStack =
llvm::ReverseStackTrace(PrettyStackTraceHead);
for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
Entry = Entry->getNextEntry()) {
OS << ID++ << ".\t";
sys::Watchdog W(5); sys::Watchdog W(5);
Entry->print(OS); Entry->print(OS);
} }
llvm::ReverseStackTrace(ReversedStack);
return NextID+1;
} }
/// PrintCurStackTrace - Print the current stack trace to the specified stream. /// PrintCurStackTrace - Print the current stack trace to the specified stream.
@ -60,7 +74,7 @@ static void PrintCurStackTrace(raw_ostream &OS) {
// If there are pretty stack frames registered, walk and emit them. // If there are pretty stack frames registered, walk and emit them.
OS << "Stack dump:\n"; OS << "Stack dump:\n";
PrintStack(PrettyStackTraceHead, OS); PrintStack(OS);
OS.flush(); OS.flush();
} }
@ -123,7 +137,7 @@ PrettyStackTraceEntry::~PrettyStackTraceEntry() {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
assert(PrettyStackTraceHead == this && assert(PrettyStackTraceHead == this &&
"Pretty stack trace entry destruction is out of order"); "Pretty stack trace entry destruction is out of order");
PrettyStackTraceHead = getNextEntry(); PrettyStackTraceHead = NextEntry;
#endif #endif
} }
@ -154,7 +168,7 @@ void llvm::EnablePrettyStackTrace() {
#endif #endif
} }
const void* llvm::SavePrettyStackState() { const void *llvm::SavePrettyStackState() {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
return PrettyStackTraceHead; return PrettyStackTraceHead;
#else #else
@ -162,9 +176,9 @@ const void* llvm::SavePrettyStackState() {
#endif #endif
} }
void llvm::RestorePrettyStackState(const void* Top) { void llvm::RestorePrettyStackState(const void *Top) {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
PrettyStackTraceHead = (const PrettyStackTraceEntry*)Top; PrettyStackTraceHead = (PrettyStackTraceEntry*)Top;
#endif #endif
} }