diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 | 
| commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
| tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /llvm/lib/Support/CrashRecoveryContext.cpp | |
| parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) | |
Notes
Diffstat (limited to 'llvm/lib/Support/CrashRecoveryContext.cpp')
| -rw-r--r-- | llvm/lib/Support/CrashRecoveryContext.cpp | 73 | 
1 files changed, 58 insertions, 15 deletions
| diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp index 9d13fce9cc52a..b9031f52375c3 100644 --- a/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/llvm/lib/Support/CrashRecoveryContext.cpp @@ -10,9 +10,17 @@  #include "llvm/Config/llvm-config.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Signals.h"  #include "llvm/Support/ThreadLocal.h"  #include <mutex>  #include <setjmp.h> +#ifdef _WIN32 +#include <excpt.h> // for GetExceptionInformation +#endif +#if LLVM_ON_UNIX +#include <sysexits.h> // EX_IOERR +#endif +  using namespace llvm;  namespace { @@ -54,7 +62,11 @@ public:  #endif    } -  void HandleCrash() { +  // 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) {      // Eliminate the current context entry, to avoid re-entering in case the      // cleanup code crashes.      CurrentContext->set(Next); @@ -62,7 +74,10 @@ public:      assert(!Failed && "Crash recovery context already failed!");      Failed = true; -    // FIXME: Stash the backtrace. +    if (CRC->DumpStackAndCleanupOnFailure) +      sys::CleanupOnSignal(Context); + +    CRC->RetCode = RetCode;      // Jump back to the RunSafely we were called under.      longjmp(JumpBuffer, 1); @@ -171,19 +186,32 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {  static void installExceptionOrSignalHandlers() {}  static void uninstallExceptionOrSignalHandlers() {} -bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { -  if (!gCrashRecoveryEnabled) { +// 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); +  return EXCEPTION_EXECUTE_HANDLER; +} + +static bool InvokeFunctionCall(function_ref<void()> Fn, +                               bool DumpStackAndCleanup, int &RetCode) { +  __try {      Fn(); -    return true; +  } __except (ExceptionFilter(DumpStackAndCleanup, GetExceptionInformation())) { +    RetCode = GetExceptionCode(); +    return false;    } +  return true; +} -  bool Result = true; -  __try { +bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { +  if (!gCrashRecoveryEnabled) {      Fn(); -  } __except (1) { // Catch any exception. -    Result = false; +    return true;    } -  return Result; +  return InvokeFunctionCall(Fn, DumpStackAndCleanupOnFailure, RetCode);  }  #else // !_MSC_VER @@ -237,7 +265,9 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)    // implementation if we so choose.    // Handle the crash -  const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash(); +  const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash( +      (int)ExceptionInfo->ExceptionRecord->ExceptionCode, +      reinterpret_cast<uintptr_t>(ExceptionInfo));    // Note that we don't actually get here because HandleCrash calls    // longjmp, which means the HandleCrash function never returns. @@ -280,7 +310,7 @@ static void uninstallExceptionOrSignalHandlers() {  // crash recovery context, and install signal handlers to invoke HandleCrash on  // the active object.  // -// This implementation does not to attempt to chain signal handlers in any +// This implementation does not 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. @@ -319,8 +349,16 @@ 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(); +    const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal);  }  static void installExceptionOrSignalHandlers() { @@ -364,7 +402,9 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {  void CrashRecoveryContext::HandleCrash() {    CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;    assert(CRCI && "Crash recovery context never initialized!"); -  CRCI->HandleCrash(); +  // As per convention, -2 indicates a crash or timeout as opposed to failure to +  // execute (see llvm/include/llvm/Support/Program.h) +  CRCI->HandleCrash(-2, 0);  }  // FIXME: Portability. @@ -404,7 +444,10 @@ 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); +  llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, +                         RequestedStackSize == 0 +                             ? llvm::None +                             : llvm::Optional<unsigned>(RequestedStackSize));    if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)      CRC->setSwitchedThread();    return Info.Result; | 
