11 #include "llvm/Config/config.h"
21 struct CrashRecoveryContextImpl;
26 struct CrashRecoveryContextImpl {
28 std::string Backtrace;
30 volatile unsigned Failed : 1;
31 unsigned SwitchedThread : 1;
36 SwitchedThread(
false) {
37 CurrentContext->set(
this);
39 ~CrashRecoveryContextImpl() {
41 CurrentContext->erase();
46 void setSwitchedThread() { SwitchedThread =
true; }
51 CurrentContext->erase();
53 assert(!Failed &&
"Crash recovery context already failed!");
59 longjmp(JumpBuffer, 1);
86 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
98 const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
111 cleanup->next = head;
119 if (cleanup == head) {
120 head = cleanup->next;
122 head->prev =
nullptr;
125 cleanup->prev->next = cleanup->next;
127 cleanup->next->prev = cleanup->prev;
154 static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
157 const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
163 return EXCEPTION_CONTINUE_SEARCH;
170 const_cast<CrashRecoveryContextImpl*
>(CRCI)->HandleCrash();
196 PVOID handle = ::AddVectoredExceptionHandler(1, ExceptionHandler);
197 sCurrentExceptionHandle.set(handle);
208 PVOID currentHandle =
const_cast<PVOID
>(sCurrentExceptionHandle.get());
211 ::RemoveVectoredExceptionHandler(currentHandle);
214 sCurrentExceptionHandle.set(NULL);
234 { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
240 const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
262 sigemptyset(&SigMask);
263 sigaddset(&SigMask, Signal);
264 sigprocmask(SIG_UNBLOCK, &SigMask,
nullptr);
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 setpriority(PRIO_DARWIN_THREAD, 0, PRIO_DARWIN_BG);
342 return getpriority(PRIO_DARWIN_THREAD, 0) == 1;
349 struct RunSafelyOnThreadInfo {
352 bool UseBackgroundPriority;
358 RunSafelyOnThreadInfo *Info =
359 reinterpret_cast<RunSafelyOnThreadInfo*
>(UserData);
361 if (Info->UseBackgroundPriority)
364 Info->Result = Info->CRC->RunSafely(Info->Fn);
367 unsigned RequestedStackSize) {
369 RunSafelyOnThreadInfo Info = { Fn,
this, UseBackgroundPriority,
false };
371 if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
372 CRC->setSwitchedThread();
ThreadLocal - A class used to abstract thread-local storage.
static const int Signals[]
An efficient, type-erasing, non-owning reference to a callable.
static CrashRecoveryContext * GetCurrent()
Return the active context, if the code is currently executing in a thread which is in a protected con...
static bool hasThreadBackgroundPriority()
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
void HandleCrash()
Explicitly trigger a crash recovery in the current process, and return failure from RunSafely()...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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
bool RunSafelyOnThread(function_ref< void()>, unsigned RequestedStackSize=0)
Execute the provide callback function (with the given arguments) in a protected context which is run ...
void registerCleanup(CrashRecoveryContextCleanup *cleanup)
static void CrashRecoverySignalHandler(int Signal)
void llvm_execute_on_thread(void(*UserFn)(void *), void *UserData, unsigned RequestedStackSize=0)
llvm_execute_on_thread - Execute the given UserFn on a separate thread, passing it the provided UserD...
virtual void recoverResources()=0
static const unsigned NumSignals
bool RunSafely(function_ref< void()> Fn)
Execute the provide callback function (with the given arguments) in a protected context.
Crash recovery helper object.
static void setThreadBackgroundPriority()
static bool gCrashRecoveryEnabled
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
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]