aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp118
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;