llvm.org GIT mirror llvm / a57926b
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 Nico Weber 5 years ago
2 changed file(s) with 14 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
3838 ///
3939 /// ... no crash was detected ...
4040 /// }
41 ///
42 /// Crash recovery contexts may not be nested.
4341 class CrashRecoveryContext {
4442 void *Impl;
4543 CrashRecoveryContextCleanup *head;
2323 sys::ThreadLocal > CurrentContext;
2424
2525 struct CrashRecoveryContextImpl {
26 const CrashRecoveryContextImpl *Next;
27
2628 CrashRecoveryContext *CRC;
2729 std::string Backtrace;
2830 ::jmp_buf JumpBuffer;
3335 CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
3436 Failed(false),
3537 SwitchedThread(false) {
38 Next = CurrentContext->get();
3639 CurrentContext->set(this);
3740 }
3841 ~CrashRecoveryContextImpl() {
3942 if (!SwitchedThread)
40 CurrentContext->erase();
43 CurrentContext->set(Next);
4144 }
4245
4346 /// \brief Called when the separate crash-recovery thread was finished, to
4447 /// indicate that we don't need to clear the thread-local CurrentContext.
45 void setSwitchedThread() { SwitchedThread = true; }
48 void setSwitchedThread() {
49 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
50 SwitchedThread = true;
51 #endif
52 }
4653
4754 void HandleCrash() {
4855 // Eliminate the current context entry, to avoid re-entering in case the
4956 // cleanup code crashes.
50 CurrentContext->erase();
57 CurrentContext->set(Next);
5158
5259 assert(!Failed && "Crash recovery context already failed!");
5360 Failed = true;
6471 static ManagedStatic gCrashRecoveryContextMutex;
6572 static bool gCrashRecoveryEnabled = false;
6673
67 static ManagedStaticCleanup> >
74 static ManagedStatic>>
6875 tlIsRecoveringFromCrash;
6976
7077 CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
7279 CrashRecoveryContext::~CrashRecoveryContext() {
7380 // Reclaim registered resources.
7481 CrashRecoveryContextCleanup *i = head;
75 tlIsRecoveringFromCrash->set(head);
82 const CrashRecoveryContext *PC = tlIsRecoveringFromCrash->get();
83 tlIsRecoveringFromCrash->set(this);
7684 while (i) {
7785 CrashRecoveryContextCleanup *tmp = i;
7886 i = tmp->next;
8088 tmp->recoverResources();
8189 delete tmp;
8290 }
83 tlIsRecoveringFromCrash->erase();
91 tlIsRecoveringFromCrash->set(PC);
8492
8593 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
8694 delete CRCI;