LLVM  14.0.0git
CrashRecoveryContext.cpp
Go to the documentation of this file.
1 //===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/Config/llvm-config.h"
12 #include "llvm/Support/ExitCodes.h"
14 #include "llvm/Support/Signals.h"
16 #include "llvm/Support/thread.h"
17 #include <mutex>
18 #include <setjmp.h>
19 
20 using namespace llvm;
21 
22 namespace {
23 
24 struct CrashRecoveryContextImpl;
25 
26 static ManagedStatic<
28 
29 struct CrashRecoveryContextImpl {
30  // When threads are disabled, this links up all active
31  // CrashRecoveryContextImpls. When threads are enabled there's one thread
32  // per CrashRecoveryContext and CurrentContext is a thread-local, so only one
33  // CrashRecoveryContextImpl is active per thread and this is always null.
34  const CrashRecoveryContextImpl *Next;
35 
37  ::jmp_buf JumpBuffer;
38  volatile unsigned Failed : 1;
39  unsigned SwitchedThread : 1;
40  unsigned ValidJumpBuffer : 1;
41 
42 public:
43  CrashRecoveryContextImpl(CrashRecoveryContext *CRC) noexcept
44  : CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) {
45  Next = CurrentContext->get();
46  CurrentContext->set(this);
47  }
48  ~CrashRecoveryContextImpl() {
49  if (!SwitchedThread)
50  CurrentContext->set(Next);
51  }
52 
53  /// Called when the separate crash-recovery thread was finished, to
54  /// indicate that we don't need to clear the thread-local CurrentContext.
55  void setSwitchedThread() {
56 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
57  SwitchedThread = true;
58 #endif
59  }
60 
61  // If the function ran by the CrashRecoveryContext crashes or fails, then
62  // 'RetCode' represents the returned error code, as if it was returned by a
63  // process. 'Context' represents the signal type on Unix; on Windows, it is
64  // the ExceptionContext.
65  void HandleCrash(int RetCode, uintptr_t Context) {
66  // Eliminate the current context entry, to avoid re-entering in case the
67  // cleanup code crashes.
68  CurrentContext->set(Next);
69 
70  assert(!Failed && "Crash recovery context already failed!");
71  Failed = true;
72 
75 
76  CRC->RetCode = RetCode;
77 
78  // Jump back to the RunSafely we were called under.
79  if (ValidJumpBuffer)
80  longjmp(JumpBuffer, 1);
81 
82  // Otherwise let the caller decide of the outcome of the crash. Currently
83  // this occurs when using SEH on Windows with MSVC or clang-cl.
84  }
85 };
86 } // namespace
87 
89 static bool gCrashRecoveryEnabled = false;
90 
93 
96 
98 
100  // On Windows, if abort() was previously triggered (and caught by a previous
101  // CrashRecoveryContext) the Windows CRT removes our installed signal handler,
102  // so we need to install it again.
104 }
105 
107  // Reclaim registered resources.
110  tlIsRecoveringFromCrash->set(this);
111  while (i) {
113  i = tmp->next;
114  tmp->cleanupFired = true;
115  tmp->recoverResources();
116  delete tmp;
117  }
118  tlIsRecoveringFromCrash->set(PC);
119 
120  CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
121  delete CRCI;
122 }
123 
125  return tlIsRecoveringFromCrash->get() != nullptr;
126 }
127 
130  return nullptr;
131 
132  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
133  if (!CRCI)
134  return nullptr;
135 
136  return CRCI->CRC;
137 }
138 
140  std::lock_guard<std::mutex> L(*gCrashRecoveryContextMutex);
141  // FIXME: Shouldn't this be a refcount or something?
143  return;
144  gCrashRecoveryEnabled = true;
146 }
147 
149  std::lock_guard<std::mutex> L(*gCrashRecoveryContextMutex);
151  return;
152  gCrashRecoveryEnabled = false;
154 }
155 
157 {
158  if (!cleanup)
159  return;
160  if (head)
161  head->prev = cleanup;
162  cleanup->next = head;
163  head = cleanup;
164 }
165 
166 void
168  if (!cleanup)
169  return;
170  if (cleanup == head) {
171  head = cleanup->next;
172  if (head)
173  head->prev = nullptr;
174  }
175  else {
176  cleanup->prev->next = cleanup->next;
177  if (cleanup->next)
178  cleanup->next->prev = cleanup->prev;
179  }
180  delete cleanup;
181 }
182 
183 #if defined(_MSC_VER)
184 
185 #include <windows.h> // for GetExceptionInformation
186 
187 // If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way
188 // better than VEH. Vectored exception handling catches all exceptions happening
189 // on the thread with installed exception handlers, so it can interfere with
190 // internal exception handling of other libraries on that thread. SEH works
191 // exactly as you would expect normal exception handling to work: it only
192 // catches exceptions if they would bubble out from the stack frame with __try /
193 // __except.
194 
195 static void installExceptionOrSignalHandlers() {}
196 static void uninstallExceptionOrSignalHandlers() {}
197 
198 // We need this function because the call to GetExceptionInformation() can only
199 // occur inside the __except evaluation block
200 static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
201  // Lookup the current thread local recovery object.
202  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
203 
204  if (!CRCI) {
205  // Something has gone horribly wrong, so let's just tell everyone
206  // to keep searching
208  return EXCEPTION_CONTINUE_SEARCH;
209  }
210 
211  int RetCode = (int)Except->ExceptionRecord->ExceptionCode;
212  if ((RetCode & 0xF0000000) == 0xE0000000)
213  RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
214 
215  // Handle the crash
216  const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
217  RetCode, reinterpret_cast<uintptr_t>(Except));
218 
219  return EXCEPTION_EXECUTE_HANDLER;
220 }
221 
222 #if defined(__clang__) && defined(_M_IX86)
223 // Work around PR44697.
224 __attribute__((optnone))
225 #endif
227  if (!gCrashRecoveryEnabled) {
228  Fn();
229  return true;
230  }
231  assert(!Impl && "Crash recovery context already initialized!");
232  Impl = new CrashRecoveryContextImpl(this);
233  __try {
234  Fn();
235  } __except (ExceptionFilter(GetExceptionInformation())) {
236  return false;
237  }
238  return true;
239 }
240 
241 #else // !_MSC_VER
242 
243 #if defined(_WIN32)
244 // This is a non-MSVC compiler, probably mingw gcc or clang without
245 // -fms-extensions. Use vectored exception handling (VEH).
246 //
247 // On Windows, we can make use of vectored exception handling to catch most
248 // crashing situations. Note that this does mean we will be alerted of
249 // exceptions *before* structured exception handling has the opportunity to
250 // catch it. Unfortunately, this causes problems in practice with other code
251 // running on threads with LLVM crash recovery contexts, so we would like to
252 // eventually move away from VEH.
253 //
254 // Vectored works on a per-thread basis, which is an advantage over
255 // SetUnhandledExceptionFilter. SetUnhandledExceptionFilter also doesn't have
256 // any native support for chaining exception handlers, but VEH allows more than
257 // one.
258 //
259 // The vectored exception handler functionality was added in Windows
260 // XP, so if support for older versions of Windows is required,
261 // it will have to be added.
262 
264 
265 static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
266 {
267  // DBG_PRINTEXCEPTION_WIDE_C is not properly defined on all supported
268  // compilers and platforms, so we define it manually.
269  constexpr ULONG DbgPrintExceptionWideC = 0x4001000AL;
270  switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
271  {
272  case DBG_PRINTEXCEPTION_C:
273  case DbgPrintExceptionWideC:
274  case 0x406D1388: // set debugger thread name
275  return EXCEPTION_CONTINUE_EXECUTION;
276  }
277 
278  // Lookup the current thread local recovery object.
279  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
280 
281  if (!CRCI) {
282  // Something has gone horribly wrong, so let's just tell everyone
283  // to keep searching
285  return EXCEPTION_CONTINUE_SEARCH;
286  }
287 
288  // TODO: We can capture the stack backtrace here and store it on the
289  // implementation if we so choose.
290 
291  int RetCode = (int)ExceptionInfo->ExceptionRecord->ExceptionCode;
292  if ((RetCode & 0xF0000000) == 0xE0000000)
293  RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
294 
295  // Handle the crash
296  const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
297  RetCode, reinterpret_cast<uintptr_t>(ExceptionInfo));
298 
299  // Note that we don't actually get here because HandleCrash calls
300  // longjmp, which means the HandleCrash function never returns.
301  llvm_unreachable("Handled the crash, should have longjmp'ed out of here");
302 }
303 
304 // Because the Enable and Disable calls are static, it means that
305 // there may not actually be an Impl available, or even a current
306 // CrashRecoveryContext at all. So we make use of a thread-local
307 // exception table. The handles contained in here will either be
308 // non-NULL, valid VEH handles, or NULL.
309 static sys::ThreadLocal<const void> sCurrentExceptionHandle;
310 
311 static void installExceptionOrSignalHandlers() {
312  // We can set up vectored exception handling now. We will install our
313  // handler as the front of the list, though there's no assurances that
314  // it will remain at the front (another call could install itself before
315  // our handler). This 1) isn't likely, and 2) shouldn't cause problems.
316  PVOID handle = ::AddVectoredExceptionHandler(1, ExceptionHandler);
317  sCurrentExceptionHandle.set(handle);
318 }
319 
321  PVOID currentHandle = const_cast<PVOID>(sCurrentExceptionHandle.get());
322  if (currentHandle) {
323  // Now we can remove the vectored exception handler from the chain
324  ::RemoveVectoredExceptionHandler(currentHandle);
325 
326  // Reset the handle in our thread-local set.
327  sCurrentExceptionHandle.set(NULL);
328  }
329 }
330 
331 #else // !_WIN32
332 
333 // Generic POSIX implementation.
334 //
335 // This implementation relies on synchronous signals being delivered to the
336 // current thread. We use a thread local object to keep track of the active
337 // crash recovery context, and install signal handlers to invoke HandleCrash on
338 // the active object.
339 //
340 // This implementation does not attempt to chain signal handlers in any
341 // reliable fashion -- if we get a signal outside of a crash recovery context we
342 // simply disable crash recovery and raise the signal again.
343 
344 #include <signal.h>
345 
346 static const int Signals[] =
347  { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
348 static const unsigned NumSignals = array_lengthof(Signals);
349 static struct sigaction PrevActions[NumSignals];
350 
351 static void CrashRecoverySignalHandler(int Signal) {
352  // Lookup the current thread local recovery object.
353  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
354 
355  if (!CRCI) {
356  // We didn't find a crash recovery context -- this means either we got a
357  // signal on a thread we didn't expect it on, the application got a signal
358  // outside of a crash recovery context, or something else went horribly
359  // wrong.
360  //
361  // Disable crash recovery and raise the signal again. The assumption here is
362  // that the enclosing application will terminate soon, and we won't want to
363  // attempt crash recovery again.
364  //
365  // This call of Disable isn't thread safe, but it doesn't actually matter.
367  raise(Signal);
368 
369  // The signal will be thrown once the signal mask is restored.
370  return;
371  }
372 
373  // Unblock the signal we received.
374  sigset_t SigMask;
375  sigemptyset(&SigMask);
376  sigaddset(&SigMask, Signal);
377  sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
378 
379  // Return the same error code as if the program crashed, as mentioned in the
380  // section "Exit Status for Commands":
381  // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
382  int RetCode = 128 + Signal;
383 
384  // Don't consider a broken pipe as a crash (see clang/lib/Driver/Driver.cpp)
385  if (Signal == SIGPIPE)
386  RetCode = EX_IOERR;
387 
388  if (CRCI)
389  const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal);
390 }
391 
393  // Setup the signal handler.
394  struct sigaction Handler;
395  Handler.sa_handler = CrashRecoverySignalHandler;
396  Handler.sa_flags = 0;
397  sigemptyset(&Handler.sa_mask);
398 
399  for (unsigned i = 0; i != NumSignals; ++i) {
400  sigaction(Signals[i], &Handler, &PrevActions[i]);
401  }
402 }
403 
405  // Restore the previous signal handlers.
406  for (unsigned i = 0; i != NumSignals; ++i)
407  sigaction(Signals[i], &PrevActions[i], nullptr);
408 }
409 
410 #endif // !_WIN32
411 
413  // If crash recovery is disabled, do nothing.
414  if (gCrashRecoveryEnabled) {
415  assert(!Impl && "Crash recovery context already initialized!");
416  CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
417  Impl = CRCI;
418 
419  CRCI->ValidJumpBuffer = true;
420  if (setjmp(CRCI->JumpBuffer) != 0) {
421  return false;
422  }
423  }
424 
425  Fn();
426  return true;
427 }
428 
429 #endif // !_MSC_VER
430 
431 [[noreturn]] void CrashRecoveryContext::HandleExit(int RetCode) {
432 #if defined(_WIN32)
433  // SEH and VEH
434  ::RaiseException(0xE0000000 | RetCode, 0, 0, NULL);
435 #else
436  // On Unix we don't need to raise an exception, we go directly to
437  // HandleCrash(), then longjmp will unwind the stack for us.
438  CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *)Impl;
439  assert(CRCI && "Crash recovery context never initialized!");
440  CRCI->HandleCrash(RetCode, 0 /*no sig num*/);
441 #endif
442  llvm_unreachable("Most likely setjmp wasn't called!");
443 }
444 
446 #if defined(_WIN32)
447  // On Windows, the high bits are reserved for kernel return codes. Values
448  // starting with 0x80000000 are reserved for "warnings"; values of 0xC0000000
449  // and up are for "errors". In practice, both are interpreted as a
450  // non-continuable signal.
451  unsigned Code = ((unsigned)RetCode & 0xF0000000) >> 28;
452  if (Code != 0xC && Code != 8)
453  return false;
454  ::RaiseException(RetCode, 0, 0, NULL);
455 #else
456  // On Unix, signals are represented by return codes of 128 or higher.
457  // Exit code 128 is a reserved value and should not be raised as a signal.
458  if (RetCode <= 128)
459  return false;
461  raise(RetCode - 128);
462 #endif
463  return true;
464 }
465 
466 // FIXME: Portability.
468 #ifdef __APPLE__
469  setpriority(PRIO_DARWIN_THREAD, 0, PRIO_DARWIN_BG);
470 #endif
471 }
472 
474 #ifdef __APPLE__
475  return getpriority(PRIO_DARWIN_THREAD, 0) == 1;
476 #else
477  return false;
478 #endif
479 }
480 
481 namespace {
482 struct RunSafelyOnThreadInfo {
483  function_ref<void()> Fn;
485  bool UseBackgroundPriority;
486  bool Result;
487 };
488 } // namespace
489 
490 static void RunSafelyOnThread_Dispatch(void *UserData) {
491  RunSafelyOnThreadInfo *Info =
492  reinterpret_cast<RunSafelyOnThreadInfo*>(UserData);
493 
494  if (Info->UseBackgroundPriority)
496 
497  Info->Result = Info->CRC->RunSafely(Info->Fn);
498 }
500  unsigned RequestedStackSize) {
501  bool UseBackgroundPriority = hasThreadBackgroundPriority();
502  RunSafelyOnThreadInfo Info = { Fn, this, UseBackgroundPriority, false };
503  llvm::thread Thread(RequestedStackSize == 0
504  ? llvm::None
505  : llvm::Optional<unsigned>(RequestedStackSize),
507  Thread.join();
508 
509  if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
510  CRC->setSwitchedThread();
511  return Info.Result;
512 }
i
i
Definition: README.txt:29
llvm::CrashRecoveryContext::Enable
static void Enable()
Enable crash recovery.
Definition: CrashRecoveryContext.cpp:139
hasThreadBackgroundPriority
static bool hasThreadBackgroundPriority()
Definition: CrashRecoveryContext.cpp:473
PrevActions
static struct sigaction PrevActions[NumSignals]
Definition: CrashRecoveryContext.cpp:349
Signals.h
tlIsRecoveringFromCrash
static ManagedStatic< sys::ThreadLocal< const CrashRecoveryContext > > tlIsRecoveringFromCrash
Definition: CrashRecoveryContext.cpp:92
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::CrashRecoveryContext::throwIfCrash
static bool throwIfCrash(int RetCode)
Throw again a signal or an exception, after it was catched once by a CrashRecoveryContext.
Definition: CrashRecoveryContext.cpp:445
Thread
uint64_t Thread
Definition: Profile.cpp:48
llvm::tgtok::Code
@ Code
Definition: TGLexer.h:50
llvm::CrashRecoveryContext::RetCode
int RetCode
In case of a crash, this is the crash identifier.
Definition: CrashRecoveryContext.h:109
ErrorHandling.h
ManagedStatic.h
cleanup
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
Definition: BlockFrequencyInfoImpl.cpp:304
WindowsSupport.h
llvm::CrashRecoveryContext::registerCleanup
void registerCleanup(CrashRecoveryContextCleanup *cleanup)
Register cleanup handler, which is used when the recovery context is finished.
Definition: CrashRecoveryContext.cpp:156
setThreadBackgroundPriority
static void setThreadBackgroundPriority()
Definition: CrashRecoveryContext.cpp:467
llvm::CrashRecoveryContext::~CrashRecoveryContext
~CrashRecoveryContext()
Definition: CrashRecoveryContext.cpp:106
llvm::Optional< unsigned >
tmp
alloca< 16 x float >, align 16 %tmp2=alloca< 16 x float >, align 16 store< 16 x float > %A,< 16 x float > *%tmp %s=bitcast< 16 x float > *%tmp to i8 *%s2=bitcast< 16 x float > *%tmp2 to i8 *call void @llvm.memcpy.i64(i8 *%s, i8 *%s2, i64 64, i32 16) %R=load< 16 x float > *%tmp2 ret< 16 x float > %R } declare void @llvm.memcpy.i64(i8 *nocapture, i8 *nocapture, i64, i32) nounwind which compiles to:_foo:subl $140, %esp movaps %xmm3, 112(%esp) movaps %xmm2, 96(%esp) movaps %xmm1, 80(%esp) movaps %xmm0, 64(%esp) movl 60(%esp), %eax movl %eax, 124(%esp) movl 56(%esp), %eax movl %eax, 120(%esp) movl 52(%esp), %eax< many many more 32-bit copies > movaps(%esp), %xmm0 movaps 16(%esp), %xmm1 movaps 32(%esp), %xmm2 movaps 48(%esp), %xmm3 addl $140, %esp ret On Nehalem, it may even be cheaper to just use movups when unaligned than to fall back to lower-granularity chunks. Implement processor-specific optimizations for parity with GCC on these processors. GCC does two optimizations:1. ix86_pad_returns inserts a noop before ret instructions if immediately preceded by a conditional branch or is the target of a jump. 2. ix86_avoid_jump_misspredicts inserts noops in cases where a 16-byte block of code contains more than 3 branches. The first one is done for all AMDs, Core2, and "Generic" The second one is done for:Atom, Pentium Pro, all AMDs, Pentium 4, Nocona, Core 2, and "Generic" Testcase:int x(int a) { return(a &0xf0)> >4 tmp
Definition: README.txt:1347
handle
then ret i32 result Tail recursion elimination should handle
Definition: README.txt:355
llvm::CrashRecoveryContext::RunSafelyOnThread
bool RunSafelyOnThread(function_ref< void()>, unsigned RequestedStackSize=0)
Execute the provide callback function (with the given arguments) in a protected context which is run ...
Definition: CrashRecoveryContext.cpp:499
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::CrashRecoveryContext::RunSafely
bool RunSafely(function_ref< void()> Fn)
Execute the provided callback function (with the given arguments) in a protected context.
Definition: CrashRecoveryContext.cpp:412
llvm::Failed
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition: Error.h:198
ExitCodes.h
uninstallExceptionOrSignalHandlers
static void uninstallExceptionOrSignalHandlers()
Definition: CrashRecoveryContext.cpp:404
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::ManagedStatic
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
llvm::CrashRecoveryContext::Disable
static void Disable()
Disable crash recovery.
Definition: CrashRecoveryContext.cpp:148
llvm::CrashRecoveryContext::isRecoveringFromCrash
static bool isRecoveringFromCrash()
Return true if the current thread is recovering from a crash.
Definition: CrashRecoveryContext.cpp:124
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
gCrashRecoveryContextMutex
static ManagedStatic< std::mutex > gCrashRecoveryContextMutex
Definition: CrashRecoveryContext.cpp:88
llvm::array_lengthof
constexpr size_t array_lengthof(T(&)[N])
Find the length of an array.
Definition: STLExtras.h:1394
llvm::None
const NoneType None
Definition: None.h:23
llvm::sys::DisableSystemDialogsOnCrash
void DisableSystemDialogsOnCrash()
Disable all system dialog boxes that appear when the process crashes.
ThreadLocal.h
llvm::CrashRecoveryContext::DumpStackAndCleanupOnFailure
bool DumpStackAndCleanupOnFailure
Selects whether handling of failures should be done in the same way as for regular crashes.
Definition: CrashRecoveryContext.h:114
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
llvm::CrashRecoveryContextCleanup
Abstract base class of cleanup handlers.
Definition: CrashRecoveryContext.h:124
RunSafelyOnThread_Dispatch
static void RunSafelyOnThread_Dispatch(void *UserData)
Definition: CrashRecoveryContext.cpp:490
llvm::thread
LLVM thread following std::thread interface with added constructor to specify stack size.
Definition: thread.h:38
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
CrashRecoverySignalHandler
static void CrashRecoverySignalHandler(int Signal)
Definition: CrashRecoveryContext.cpp:351
llvm::sys::ThreadLocal::get
T * get()
get - Fetches a pointer to the object associated with the current thread.
Definition: ThreadLocal.h:51
llvm::CrashRecoveryContext::GetCurrent
static CrashRecoveryContext * GetCurrent()
Return the active context, if the code is currently executing in a thread which is in a protected con...
Definition: CrashRecoveryContext.cpp:128
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
llvm::CrashRecoveryContext::HandleExit
void HandleExit(int RetCode)
Explicitly trigger a crash recovery in the current process, and return failure from RunSafely().
Definition: CrashRecoveryContext.cpp:431
llvm::sys::unregisterHandlers
void unregisterHandlers()
Signals
static const int Signals[]
Definition: CrashRecoveryContext.cpp:346
installExceptionOrSignalHandlers
static void installExceptionOrSignalHandlers()
Definition: CrashRecoveryContext.cpp:392
gCrashRecoveryEnabled
static bool gCrashRecoveryEnabled
Definition: CrashRecoveryContext.cpp:89
llvm::sys::CleanupOnSignal
void CleanupOnSignal(uintptr_t Context)
This function does the following:
CrashRecoveryContext.h
llvm::CrashRecoveryContext::unregisterCleanup
void unregisterCleanup(CrashRecoveryContextCleanup *cleanup)
Definition: CrashRecoveryContext.cpp:167
llvm::sys::ThreadLocal
ThreadLocal - A class used to abstract thread-local storage.
Definition: ThreadLocal.h:45
llvm::CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup
virtual ~CrashRecoveryContextCleanup()
Definition: CrashRecoveryContext.cpp:97
thread.h
llvm::CrashRecoveryContext
Crash recovery helper object.
Definition: CrashRecoveryContext.h:46
llvm::CrashRecoveryContext::CrashRecoveryContext
CrashRecoveryContext()
Definition: CrashRecoveryContext.cpp:99
llvm::sys::ThreadLocal::set
void set(T *d)
Definition: ThreadLocal.h:54
NumSignals
static const unsigned NumSignals
Definition: CrashRecoveryContext.cpp:348