diff options
author | Alexandre Ganea <alexandre.ganea@ubisoft.com> | 2020-02-06 19:23:27 -0500 |
---|---|---|
committer | Hans Wennborg <hans@chromium.org> | 2020-02-10 15:37:12 +0100 |
commit | 4759c6ef8b4ab8d17be3a5e6c96e890944bc515d (patch) | |
tree | 32bbd791819a58c973bba5787643bd107b611c4c /llvm/lib/Support/CrashRecoveryContext.cpp | |
parent | 64515b35844b925bdb76821d03ad4d7ddebe06e7 (diff) | |
download | bcm5719-llvm-4759c6ef8b4ab8d17be3a5e6c96e890944bc515d.tar.gz bcm5719-llvm-4759c6ef8b4ab8d17be3a5e6c96e890944bc515d.zip |
[Support] When using SEH, create a impl instance for CrashRecoveryContext. NFCI.
Previously, the SEH codepath in CrashRecoveryContext didn't create a CrashRecoveryContextImpl. The other codepaths (VEH and Unix) were creating it.
When running with -fintegrated-cc1, this is needed to handle exit() as a jump to CrashRecoveryContext's exception filter, through a call to RaiseException. In that situation, we need a user-defined exception code, which is later interpreted as an exit() by the exception filter. This in turn needs to set RetCode accordingly, *inside* the exception filter, and *before* calling HandleCrash().
Differential Revision: https://reviews.llvm.org/D74078
(cherry picked from commit 2a3fa0fc5cd7d3398c0293915b0e569eaa0be24b)
Diffstat (limited to 'llvm/lib/Support/CrashRecoveryContext.cpp')
-rw-r--r-- | llvm/lib/Support/CrashRecoveryContext.cpp | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp index a24bf7bf255..0cc2d4059fe 100644 --- a/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/llvm/lib/Support/CrashRecoveryContext.cpp @@ -15,7 +15,7 @@ #include <mutex> #include <setjmp.h> #ifdef _WIN32 -#include <excpt.h> // for GetExceptionInformation +#include <windows.h> // for GetExceptionInformation #endif #if LLVM_ON_UNIX #include <sysexits.h> // EX_IOERR @@ -41,11 +41,11 @@ struct CrashRecoveryContextImpl { ::jmp_buf JumpBuffer; volatile unsigned Failed : 1; unsigned SwitchedThread : 1; + unsigned ValidJumpBuffer : 1; public: - CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC), - Failed(false), - SwitchedThread(false) { + CrashRecoveryContextImpl(CrashRecoveryContext *CRC) + : CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) { Next = CurrentContext->get(); CurrentContext->set(this); } @@ -80,10 +80,13 @@ public: CRC->RetCode = RetCode; // Jump back to the RunSafely we were called under. - longjmp(JumpBuffer, 1); + 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. } }; - } static ManagedStatic<std::mutex> gCrashRecoveryContextMutex; @@ -188,37 +191,43 @@ static void uninstallExceptionOrSignalHandlers() {} // We need this function because the call to GetExceptionInformation() can only // occur inside the __except evaluation block -static int ExceptionFilter(bool DumpStackAndCleanup, - _EXCEPTION_POINTERS *Except) { - if (DumpStackAndCleanup) - sys::CleanupOnSignal((uintptr_t)Except); +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; + + // 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)) -static bool InvokeFunctionCall(function_ref<void()> Fn, - bool DumpStackAndCleanup, int &RetCode) { -#else -static bool InvokeFunctionCall(function_ref<void()> Fn, - bool DumpStackAndCleanup, int &RetCode) { #endif - __try { - Fn(); - } __except (ExceptionFilter(DumpStackAndCleanup, GetExceptionInformation())) { - RetCode = GetExceptionCode(); - return false; - } - return true; -} - bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { if (!gCrashRecoveryEnabled) { Fn(); return true; } - return InvokeFunctionCall(Fn, DumpStackAndCleanupOnFailure, RetCode); + assert(!Impl && "Crash recovery context already initialized!"); + Impl = new CrashRecoveryContextImpl(this); + __try { + Fn(); + } __except (ExceptionFilter(GetExceptionInformation())) { + return false; + } + return true; } #else // !_MSC_VER @@ -395,6 +404,7 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this); Impl = CRCI; + CRCI->ValidJumpBuffer = true; if (setjmp(CRCI->JumpBuffer) != 0) { return false; } |