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 | e94e0984dfd22ede6211080d1f3e47138f1ea857 (patch) | |
tree | 1539ee84c9d712f6e657ee21790f26ed635b46d7 /lib/Support/PrettyStackTrace.cpp | |
parent | 98bae99266d8e527e7399c717a79c6dc9a073331 (diff) | |
download | llvm-e94e0984dfd22ede6211080d1f3e47138f1ea857.tar.gz llvm-e94e0984dfd22ede6211080d1f3e47138f1ea857.tar.bz2 llvm-e94e0984dfd22ede6211080d1f3e47138f1ea857.tar.xz |
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).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190730 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/PrettyStackTrace.cpp')
-rw-r--r-- | lib/Support/PrettyStackTrace.cpp | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp index 23ee5ab105..315008ae81 100644 --- a/lib/Support/PrettyStackTrace.cpp +++ b/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 { |