mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
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
This commit is contained in:
parent
98bae99266
commit
e94e0984df
@ -99,7 +99,6 @@ public:
|
||||
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
|
||||
void llvm_shutdown();
|
||||
|
||||
|
||||
/// llvm_shutdown_obj - This is a simple helper class that calls
|
||||
/// llvm_shutdown() when it is destroyed.
|
||||
struct llvm_shutdown_obj {
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user