diff options
author | Filip Pizlo <fpizlo@apple.com> | 2013-09-13 22:59:47 +0000 |
---|---|---|
committer | Filip Pizlo <fpizlo@apple.com> | 2013-09-13 22:59:47 +0000 |
commit | 67d97093416a2f78ffe17cf7aff39bd0c50a3f8b (patch) | |
tree | 3054e1b00d00ac0c0918938eb67cbfa3efe8fa96 /llvm/lib/Support/PrettyStackTrace.cpp | |
parent | 138c32b402e0f384fb6c72d101cfbcf7bcc5a0f9 (diff) | |
download | bcm5719-llvm-67d97093416a2f78ffe17cf7aff39bd0c50a3f8b.tar.gz bcm5719-llvm-67d97093416a2f78ffe17cf7aff39bd0c50a3f8b.zip |
Make PrettyStackTraceEntry use ManagedStatic for its ThreadLocal.
This was somewhat tricky because ~PrettyStackTraceEntry() may run after
llvm_shutdown() has been called. This is rare and only happens for a common idiom
used in the main() functions of command-line tools. This works around the idiom by
skipping the stack clean-up if the PrettyStackTraceHead ManagedStatic is not
constructed (i.e. llvm_shutdown() has been called).
llvm-svn: 190730
Diffstat (limited to 'llvm/lib/Support/PrettyStackTrace.cpp')
-rw-r--r-- | llvm/lib/Support/PrettyStackTrace.cpp | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/llvm/lib/Support/PrettyStackTrace.cpp b/llvm/lib/Support/PrettyStackTrace.cpp index 23ee5ab105a..315008ae810 100644 --- a/llvm/lib/Support/PrettyStackTrace.cpp +++ b/llvm/lib/Support/PrettyStackTrace.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Signals.h" #include "llvm/Support/ThreadLocal.h" #include "llvm/Support/Watchdog.h" @@ -30,8 +31,7 @@ namespace llvm { bool DisablePrettyStackTrace = false; } -// FIXME: This should be thread local when llvm supports threads. -static sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead; +static ManagedStatic<sys::ThreadLocal<const PrettyStackTraceEntry> > PrettyStackTraceHead; static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ unsigned NextID = 0; @@ -49,12 +49,12 @@ static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ /// PrintCurStackTrace - Print the current stack trace to the specified stream. static void PrintCurStackTrace(raw_ostream &OS) { // Don't print an empty trace. - if (PrettyStackTraceHead.get() == 0) return; + if (PrettyStackTraceHead->get() == 0) return; // If there are pretty stack frames registered, walk and emit them. OS << "Stack dump:\n"; - PrintStack(PrettyStackTraceHead.get(), OS); + PrintStack(PrettyStackTraceHead->get(), OS); OS.flush(); } @@ -114,14 +114,26 @@ PrettyStackTraceEntry::PrettyStackTraceEntry() { (void)HandlerRegistered; // Link ourselves. - NextEntry = PrettyStackTraceHead.get(); - PrettyStackTraceHead.set(this); + NextEntry = PrettyStackTraceHead->get(); + PrettyStackTraceHead->set(this); } PrettyStackTraceEntry::~PrettyStackTraceEntry() { - assert(PrettyStackTraceHead.get() == this && + // Do nothing if PrettyStackTraceHead is uninitialized. This can only happen + // if a shutdown occurred after we created the PrettyStackTraceEntry. That + // does occur in the following idiom: + // + // PrettyStackTraceProgram X(...); + // llvm_shutdown_obj Y; + // + // Without this check, we may end up removing ourselves from the stack trace + // after PrettyStackTraceHead has already been destroyed. + if (!PrettyStackTraceHead.isConstructed()) + return; + + assert(PrettyStackTraceHead->get() == this && "Pretty stack trace entry destruction is out of order"); - PrettyStackTraceHead.set(getNextEntry()); + PrettyStackTraceHead->set(getNextEntry()); } void PrettyStackTraceString::print(raw_ostream &OS) const { |