diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp | 118 |
1 files changed, 23 insertions, 95 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp index 356835609830..c2459256f8fe 100644 --- a/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp @@ -10,14 +10,9 @@ #include "llvm/Config/llvm-config.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Signals.h" +#include "llvm/Support/Mutex.h" #include "llvm/Support/ThreadLocal.h" -#include <mutex> #include <setjmp.h> -#if LLVM_ON_UNIX -#include <sysexits.h> // EX_IOERR -#endif - using namespace llvm; namespace { @@ -38,11 +33,11 @@ struct CrashRecoveryContextImpl { ::jmp_buf JumpBuffer; volatile unsigned Failed : 1; unsigned SwitchedThread : 1; - unsigned ValidJumpBuffer : 1; public: - CrashRecoveryContextImpl(CrashRecoveryContext *CRC) noexcept - : CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) { + CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC), + Failed(false), + SwitchedThread(false) { Next = CurrentContext->get(); CurrentContext->set(this); } @@ -59,11 +54,7 @@ public: #endif } - // If the function ran by the CrashRecoveryContext crashes or fails, then - // 'RetCode' represents the returned error code, as if it was returned by a - // process. 'Context' represents the signal type on Unix; on Windows, it is - // the ExceptionContext. - void HandleCrash(int RetCode, uintptr_t Context) { + void HandleCrash() { // Eliminate the current context entry, to avoid re-entering in case the // cleanup code crashes. CurrentContext->set(Next); @@ -71,22 +62,16 @@ public: assert(!Failed && "Crash recovery context already failed!"); Failed = true; - if (CRC->DumpStackAndCleanupOnFailure) - sys::CleanupOnSignal(Context); - - CRC->RetCode = RetCode; + // FIXME: Stash the backtrace. // Jump back to the RunSafely we were called under. - if (ValidJumpBuffer) - longjmp(JumpBuffer, 1); - - // Otherwise let the caller decide of the outcome of the crash. Currently - // this occurs when using SEH on Windows with MSVC or clang-cl. + longjmp(JumpBuffer, 1); } }; + } -static ManagedStatic<std::mutex> gCrashRecoveryContextMutex; +static ManagedStatic<sys::Mutex> gCrashRecoveryContextMutex; static bool gCrashRecoveryEnabled = false; static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>> @@ -131,7 +116,7 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() { } void CrashRecoveryContext::Enable() { - std::lock_guard<std::mutex> L(*gCrashRecoveryContextMutex); + sys::ScopedLock L(*gCrashRecoveryContextMutex); // FIXME: Shouldn't this be a refcount or something? if (gCrashRecoveryEnabled) return; @@ -140,7 +125,7 @@ void CrashRecoveryContext::Enable() { } void CrashRecoveryContext::Disable() { - std::lock_guard<std::mutex> L(*gCrashRecoveryContextMutex); + sys::ScopedLock L(*gCrashRecoveryContextMutex); if (!gCrashRecoveryEnabled) return; gCrashRecoveryEnabled = false; @@ -175,9 +160,6 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) { } #if defined(_MSC_VER) - -#include <windows.h> // for GetExceptionInformation - // If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way // better than VEH. Vectored exception handling catches all exceptions happening // on the thread with installed exception handlers, so it can interfere with @@ -189,47 +171,19 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) { static void installExceptionOrSignalHandlers() {} static void uninstallExceptionOrSignalHandlers() {} -// We need this function because the call to GetExceptionInformation() can only -// occur inside the __except evaluation block -static int ExceptionFilter(_EXCEPTION_POINTERS *Except) { - // Lookup the current thread local recovery object. - const CrashRecoveryContextImpl *CRCI = CurrentContext->get(); - - if (!CRCI) { - // Something has gone horribly wrong, so let's just tell everyone - // to keep searching - CrashRecoveryContext::Disable(); - return EXCEPTION_CONTINUE_SEARCH; - } - - int RetCode = (int)Except->ExceptionRecord->ExceptionCode; - if ((RetCode & 0xF0000000) == 0xE0000000) - RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit - - // Handle the crash - const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash( - RetCode, reinterpret_cast<uintptr_t>(Except)); - - return EXCEPTION_EXECUTE_HANDLER; -} - -#if defined(__clang__) && defined(_M_IX86) -// Work around PR44697. -__attribute__((optnone)) -#endif bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { if (!gCrashRecoveryEnabled) { Fn(); return true; } - assert(!Impl && "Crash recovery context already initialized!"); - Impl = new CrashRecoveryContextImpl(this); + + bool Result = true; __try { Fn(); - } __except (ExceptionFilter(GetExceptionInformation())) { - return false; + } __except (1) { // Catch any exception. + Result = false; } - return true; + return Result; } #else // !_MSC_VER @@ -282,13 +236,8 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) // TODO: We can capture the stack backtrace here and store it on the // implementation if we so choose. - int RetCode = (int)ExceptionInfo->ExceptionRecord->ExceptionCode; - if ((RetCode & 0xF0000000) == 0xE0000000) - RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit - // Handle the crash - const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash( - RetCode, reinterpret_cast<uintptr_t>(ExceptionInfo)); + const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash(); // Note that we don't actually get here because HandleCrash calls // longjmp, which means the HandleCrash function never returns. @@ -331,7 +280,7 @@ static void uninstallExceptionOrSignalHandlers() { // crash recovery context, and install signal handlers to invoke HandleCrash on // the active object. // -// This implementation does not attempt to chain signal handlers in any +// This implementation does not to attempt to chain signal handlers in any // reliable fashion -- if we get a signal outside of a crash recovery context we // simply disable crash recovery and raise the signal again. @@ -370,16 +319,8 @@ static void CrashRecoverySignalHandler(int Signal) { sigaddset(&SigMask, Signal); sigprocmask(SIG_UNBLOCK, &SigMask, nullptr); - // As per convention, -2 indicates a crash or timeout as opposed to failure to - // execute (see llvm/include/llvm/Support/Program.h) - int RetCode = -2; - - // Don't consider a broken pipe as a crash (see clang/lib/Driver/Driver.cpp) - if (Signal == SIGPIPE) - RetCode = EX_IOERR; - if (CRCI) - const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal); + const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash(); } static void installExceptionOrSignalHandlers() { @@ -409,7 +350,6 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this); Impl = CRCI; - CRCI->ValidJumpBuffer = true; if (setjmp(CRCI->JumpBuffer) != 0) { return false; } @@ -421,19 +361,10 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { #endif // !_MSC_VER -LLVM_ATTRIBUTE_NORETURN -void CrashRecoveryContext::HandleExit(int RetCode) { -#if defined(_WIN32) - // SEH and VEH - ::RaiseException(0xE0000000 | RetCode, 0, 0, NULL); -#else - // On Unix we don't need to raise an exception, we go directly to - // HandleCrash(), then longjmp will unwind the stack for us. - CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *)Impl; +void CrashRecoveryContext::HandleCrash() { + CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl; assert(CRCI && "Crash recovery context never initialized!"); - CRCI->HandleCrash(RetCode, 0 /*no sig num*/); -#endif - llvm_unreachable("Most likely setjmp wasn't called!"); + CRCI->HandleCrash(); } // FIXME: Portability. @@ -473,10 +404,7 @@ bool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn, unsigned RequestedStackSize) { bool UseBackgroundPriority = hasThreadBackgroundPriority(); RunSafelyOnThreadInfo Info = { Fn, this, UseBackgroundPriority, false }; - llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, - RequestedStackSize == 0 - ? llvm::None - : llvm::Optional<unsigned>(RequestedStackSize)); + llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize); if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl) CRC->setSwitchedThread(); return Info.Result; |
