mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 14:10:41 +00:00
Fix nested CrashRecoveryContexts with LLVM_ENABLE_THREADS=OFF, allow them.
libclang uses a CrashRecoveryContext, and building a module does too. If a module gets built through libclang, nested CrashRecoveryContexts are used. They work fine with threads as things are stored in ThreadLocal variables, but in LLVM_ENABLE_THREADS=OFF builds the two recovery contexts would write to the same globals. To fix, keep active CrashRecoveryContextImpls in a list and have the global point to the innermost one, and do something similar for tlIsRecoveringFromCrash. Necessary (but not sufficient) for PR11974 and PR20325 http://reviews.llvm.org/D11770 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244251 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
397ed3e704
commit
a57926b847
@ -39,8 +39,6 @@ class CrashRecoveryContextCleanup;
|
||||
///
|
||||
/// ... no crash was detected ...
|
||||
/// }
|
||||
///
|
||||
/// Crash recovery contexts may not be nested.
|
||||
class CrashRecoveryContext {
|
||||
void *Impl;
|
||||
CrashRecoveryContextCleanup *head;
|
||||
|
@ -24,6 +24,8 @@ static ManagedStatic<
|
||||
sys::ThreadLocal<const CrashRecoveryContextImpl> > CurrentContext;
|
||||
|
||||
struct CrashRecoveryContextImpl {
|
||||
const CrashRecoveryContextImpl *Next;
|
||||
|
||||
CrashRecoveryContext *CRC;
|
||||
std::string Backtrace;
|
||||
::jmp_buf JumpBuffer;
|
||||
@ -34,21 +36,26 @@ public:
|
||||
CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
|
||||
Failed(false),
|
||||
SwitchedThread(false) {
|
||||
Next = CurrentContext->get();
|
||||
CurrentContext->set(this);
|
||||
}
|
||||
~CrashRecoveryContextImpl() {
|
||||
if (!SwitchedThread)
|
||||
CurrentContext->erase();
|
||||
CurrentContext->set(Next);
|
||||
}
|
||||
|
||||
/// \brief Called when the separate crash-recovery thread was finished, to
|
||||
/// indicate that we don't need to clear the thread-local CurrentContext.
|
||||
void setSwitchedThread() { SwitchedThread = true; }
|
||||
void setSwitchedThread() {
|
||||
#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
|
||||
SwitchedThread = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HandleCrash() {
|
||||
// Eliminate the current context entry, to avoid re-entering in case the
|
||||
// cleanup code crashes.
|
||||
CurrentContext->erase();
|
||||
CurrentContext->set(Next);
|
||||
|
||||
assert(!Failed && "Crash recovery context already failed!");
|
||||
Failed = true;
|
||||
@ -65,7 +72,7 @@ public:
|
||||
static ManagedStatic<sys::Mutex> gCrashRecoveryContextMutex;
|
||||
static bool gCrashRecoveryEnabled = false;
|
||||
|
||||
static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContextCleanup> >
|
||||
static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>>
|
||||
tlIsRecoveringFromCrash;
|
||||
|
||||
CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
|
||||
@ -73,7 +80,8 @@ CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
|
||||
CrashRecoveryContext::~CrashRecoveryContext() {
|
||||
// Reclaim registered resources.
|
||||
CrashRecoveryContextCleanup *i = head;
|
||||
tlIsRecoveringFromCrash->set(head);
|
||||
const CrashRecoveryContext *PC = tlIsRecoveringFromCrash->get();
|
||||
tlIsRecoveringFromCrash->set(this);
|
||||
while (i) {
|
||||
CrashRecoveryContextCleanup *tmp = i;
|
||||
i = tmp->next;
|
||||
@ -81,7 +89,7 @@ CrashRecoveryContext::~CrashRecoveryContext() {
|
||||
tmp->recoverResources();
|
||||
delete tmp;
|
||||
}
|
||||
tlIsRecoveringFromCrash->erase();
|
||||
tlIsRecoveringFromCrash->set(PC);
|
||||
|
||||
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
|
||||
delete CRCI;
|
||||
|
Loading…
Reference in New Issue
Block a user