summaryrefslogtreecommitdiff
path: root/lib/Support/PrettyStackTrace.cpp
diff options
context:
space:
mode:
authorFilip Pizlo <fpizlo@apple.com>2013-09-13 22:59:47 +0000
committerFilip Pizlo <fpizlo@apple.com>2013-09-13 22:59:47 +0000
commite94e0984dfd22ede6211080d1f3e47138f1ea857 (patch)
tree1539ee84c9d712f6e657ee21790f26ed635b46d7 /lib/Support/PrettyStackTrace.cpp
parent98bae99266d8e527e7399c717a79c6dc9a073331 (diff)
downloadllvm-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.cpp28
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 {