From: Nico Weber Date: Thu, 6 Aug 2015 19:21:25 +0000 (+0000) Subject: Fix nested CrashRecoveryContexts with LLVM_ENABLE_THREADS=OFF, allow them. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=a57926b847cd89613a47e07a5af7d67b676aa240;p=oota-llvm.git 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 --- diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index c08c3c1f0d2..bedecfa14ad 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -39,8 +39,6 @@ class CrashRecoveryContextCleanup; /// /// ... no crash was detected ... /// } -/// -/// Crash recovery contexts may not be nested. class CrashRecoveryContext { void *Impl; CrashRecoveryContextCleanup *head; diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp index aba0f1ddeee..b9829e1192a 100644 --- a/lib/Support/CrashRecoveryContext.cpp +++ b/lib/Support/CrashRecoveryContext.cpp @@ -24,6 +24,8 @@ static ManagedStatic< sys::ThreadLocal > 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 gCrashRecoveryContextMutex; static bool gCrashRecoveryEnabled = false; -static ManagedStatic > +static ManagedStatic> 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;