12 #include "llvm/Config/config.h"
23 struct CrashRecoveryContextImpl;
27 struct CrashRecoveryContextImpl {
29 std::string Backtrace;
31 volatile unsigned Failed : 1;
32 unsigned SwitchedThread : 1;
37 SwitchedThread(
false) {
38 CurrentContext->set(
this);
40 ~CrashRecoveryContextImpl() {
42 CurrentContext->erase();
47 void setSwitchedThread() { SwitchedThread =
true; }
52 CurrentContext->erase();
54 assert(!Failed &&
"Crash recovery context already failed!");
87 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
99 const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
111 head->prev = cleanup;
112 cleanup->next = head;
120 if (cleanup == head) {
121 head = cleanup->next;
126 cleanup->prev->next = cleanup->next;
128 cleanup->next->prev = cleanup->prev;
155 static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
158 const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
164 return EXCEPTION_CONTINUE_SEARCH;
171 const_cast<CrashRecoveryContextImpl*
>(CRCI)->HandleCrash();
197 PVOID handle = ::AddVectoredExceptionHandler(1, ExceptionHandler);
198 sCurrentExceptionHandle.set(handle);
209 PVOID currentHandle =
const_cast<PVOID
>(sCurrentExceptionHandle.get());
212 ::RemoveVectoredExceptionHandler(currentHandle);
215 sCurrentExceptionHandle.set(NULL);
234 static const int Signals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
240 const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
262 sigemptyset(&SigMask);
263 sigaddset(&SigMask, Signal);
264 sigprocmask(SIG_UNBLOCK, &SigMask, 0);
267 const_cast<CrashRecoveryContextImpl*
>(CRCI)->HandleCrash();
279 struct sigaction Handler;
281 Handler.sa_flags = 0;
282 sigemptyset(&Handler.sa_mask);
307 assert(!Impl &&
"Crash recovery context already initialized!");
308 CrashRecoveryContextImpl *CRCI =
new CrashRecoveryContextImpl(
this);
311 if (
setjmp(CRCI->JumpBuffer) != 0) {
321 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
322 assert(CRCI &&
"Crash recovery context never initialized!");
327 CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl;
328 assert(CRC &&
"Crash recovery context never initialized!");
329 assert(CRC->Failed &&
"No crash was detected!");
330 return CRC->Backtrace;
336 struct RunSafelyOnThreadInfo {
337 void (*UserFn)(
void*);
345 RunSafelyOnThreadInfo *Info =
346 reinterpret_cast<RunSafelyOnThreadInfo*
>(UserData);
347 Info->Result = Info->CRC->RunSafely(Info->UserFn, Info->UserData);
350 unsigned RequestedStackSize) {
351 RunSafelyOnThreadInfo Info = { Fn, UserData,
this,
false };
353 if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
354 CRC->setSwitchedThread();
static const int Signals[]
static CrashRecoveryContext * GetCurrent()
Return the active context, if the code is currently executing in a thread which is in a protected con...
bool RunSafelyOnThread(void(*Fn)(void *), void *UserData, unsigned RequestedStackSize=0)
Execute the provide callback function (with the given arguments) in a protected context which is run ...
void HandleCrash()
Explicitly trigger a crash recovery in the current process, and return failure from RunSafely()...
#define llvm_unreachable(msg)
const std::string & getBacktrace() const
Return a string containing the backtrace where the crash was detected; or empty if the backtrace wasn...
void unregisterCleanup(CrashRecoveryContextCleanup *cleanup)
virtual ~CrashRecoveryContextCleanup()
static void Enable()
Enable crash recovery.
static ManagedStatic< sys::Mutex > gCrashRecoveryContextMutex
static ManagedStatic< sys::ThreadLocal< const CrashRecoveryContextCleanup > > tlIsRecoveringFromCrash
void registerCleanup(CrashRecoveryContextCleanup *cleanup)
static void CrashRecoverySignalHandler(int Signal)
void llvm_execute_on_thread(void(*UserFn)(void *), void *UserData, unsigned RequestedStackSize=0)
virtual void recoverResources()=0
bool RunSafely(void(*Fn)(void *), void *UserData)
Execute the provide callback function (with the given arguments) in a protected context.
static const unsigned NumSignals
Crash recovery helper object.
static bool gCrashRecoveryEnabled
static bool isRecoveringFromCrash()
Return true if the current thread is recovering from a crash.
static void RunSafelyOnThread_Dispatch(void *UserData)
static void Disable()
Disable crash recovery.
static struct sigaction PrevActions[NumSignals]