1a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar//===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===//
2a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar//
3a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar//                     The LLVM Compiler Infrastructure
4a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar//
5a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar// This file is distributed under the University of Illinois Open Source
6a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar// License. See LICENSE.TXT for details.
7a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar//
8a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar//===----------------------------------------------------------------------===//
9a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
10a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar#include "llvm/Support/CrashRecoveryContext.h"
11dade28ee4eeaa9d22dac986666de4005e1309a06Daniel Dunbar#include "llvm/Config/config.h"
12d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/ErrorHandling.h"
1363fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo#include "llvm/Support/ManagedStatic.h"
141f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h"
151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/ThreadLocal.h"
16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <setjmp.h>
17a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarusing namespace llvm;
18a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
19a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarnamespace {
20a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
21a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarstruct CrashRecoveryContextImpl;
22a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
23c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic ManagedStatic<
24c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    sys::ThreadLocal<const CrashRecoveryContextImpl> > CurrentContext;
25d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
26a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarstruct CrashRecoveryContextImpl {
27a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar  CrashRecoveryContext *CRC;
28a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  std::string Backtrace;
29a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  ::jmp_buf JumpBuffer;
30a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  volatile unsigned Failed : 1;
314e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis  unsigned SwitchedThread : 1;
32a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
33a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarpublic:
34a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar  CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
354e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis                                                        Failed(false),
364e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis                                                        SwitchedThread(false) {
3763fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo    CurrentContext->set(this);
38d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  }
39d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  ~CrashRecoveryContextImpl() {
404e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis    if (!SwitchedThread)
4163fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo      CurrentContext->erase();
42d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  }
43a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
444e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis  /// \brief Called when the separate crash-recovery thread was finished, to
454e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis  /// indicate that we don't need to clear the thread-local CurrentContext.
464e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis  void setSwitchedThread() { SwitchedThread = true; }
474e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis
48a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  void HandleCrash() {
49ebe7eb884e30c8e9e9f44f499d75ee39cc6c6d6eDaniel Dunbar    // Eliminate the current context entry, to avoid re-entering in case the
50ebe7eb884e30c8e9e9f44f499d75ee39cc6c6d6eDaniel Dunbar    // cleanup code crashes.
5163fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo    CurrentContext->erase();
52ebe7eb884e30c8e9e9f44f499d75ee39cc6c6d6eDaniel Dunbar
53a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    assert(!Failed && "Crash recovery context already failed!");
54a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    Failed = true;
55a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
56a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    // FIXME: Stash the backtrace.
57a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
58a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    // Jump back to the RunSafely we were called under.
59a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    longjmp(JumpBuffer, 1);
60a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  }
61a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar};
62a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
63a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
64a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
6563fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlostatic ManagedStatic<sys::Mutex> gCrashRecoveryContextMutex;
66a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarstatic bool gCrashRecoveryEnabled = false;
67a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
6863fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlostatic ManagedStatic<sys::ThreadLocal<const CrashRecoveryContextCleanup> >
69b52fde4185cd724f51aae4018b0f8278732379c7Ted Kremenek       tlIsRecoveringFromCrash;
70b52fde4185cd724f51aae4018b0f8278732379c7Ted Kremenek
71a4f983970133c934d6af66dc8dc50fbf908c31ddTed KremenekCrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
72a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek
73a309dac868e591d7254f570b950a50f640c009f8Daniel DunbarCrashRecoveryContext::~CrashRecoveryContext() {
74a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  // Reclaim registered resources.
75a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  CrashRecoveryContextCleanup *i = head;
7663fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  tlIsRecoveringFromCrash->set(head);
77a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  while (i) {
78a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    CrashRecoveryContextCleanup *tmp = i;
79a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    i = tmp->next;
801a06d5721acb9a2b69217fc8872ed5b14a482104Ted Kremenek    tmp->cleanupFired = true;
813311d951e22b133207ed6f8e384d80f0970a7fb3Ted Kremenek    tmp->recoverResources();
82a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    delete tmp;
83a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  }
8463fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  tlIsRecoveringFromCrash->erase();
85a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek
86a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
87a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  delete CRCI;
88a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
89a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
90b52fde4185cd724f51aae4018b0f8278732379c7Ted Kremenekbool CrashRecoveryContext::isRecoveringFromCrash() {
91dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return tlIsRecoveringFromCrash->get() != nullptr;
92b52fde4185cd724f51aae4018b0f8278732379c7Ted Kremenek}
93b52fde4185cd724f51aae4018b0f8278732379c7Ted Kremenek
94a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel DunbarCrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
95fb200e30a48c3e682742174453d9550d1dc589d5Ted Kremenek  if (!gCrashRecoveryEnabled)
96dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
97fb200e30a48c3e682742174453d9550d1dc589d5Ted Kremenek
9863fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
99a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar  if (!CRCI)
100dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
101a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar
102a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar  return CRCI->CRC;
103a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar}
104a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar
105a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenekvoid CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup)
106a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek{
107a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  if (!cleanup)
108a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    return;
109a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  if (head)
110a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    head->prev = cleanup;
111a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  cleanup->next = head;
112a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  head = cleanup;
113a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek}
114a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek
115a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenekvoid
116a4f983970133c934d6af66dc8dc50fbf908c31ddTed KremenekCrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
117a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  if (!cleanup)
118a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    return;
119a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  if (cleanup == head) {
120a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    head = cleanup->next;
121a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    if (head)
122dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      head->prev = nullptr;
123a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  }
124a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  else {
125a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    cleanup->prev->next = cleanup->next;
126a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek    if (cleanup->next)
127a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek      cleanup->next->prev = cleanup->prev;
128a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  }
129a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek  delete cleanup;
130a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek}
131a4f983970133c934d6af66dc8dc50fbf908c31ddTed Kremenek
132d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar#ifdef LLVM_ON_WIN32
133d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "Windows/WindowsSupport.h"
13577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
13677c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// On Windows, we can make use of vectored exception handling to
13777c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// catch most crashing situations.  Note that this does mean
13877c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// we will be alerted of exceptions *before* structured exception
13977c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// handling has the opportunity to catch it.  But that isn't likely
14077c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// to cause problems because nowhere in the project is SEH being
14177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// used.
14277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi//
14377c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// Vectored exception handling is built on top of SEH, and so it
14477c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// works on a per-thread basis.
14577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi//
14677c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// The vectored exception handler functionality was added in Windows
14777c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// XP, so if support for older versions of Windows is required,
14877c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// it will have to be added.
14977c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi//
15077c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// If we want to support as far back as Win2k, we could use the
15177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// SetUnhandledExceptionFilter API, but there's a risk of that
15277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// being entirely overwritten (it's not a chain).
15377c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
15477c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumistatic LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
15577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi{
15677c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // Lookup the current thread local recovery object.
15763fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
15877c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
15977c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  if (!CRCI) {
16077c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    // Something has gone horribly wrong, so let's just tell everyone
16177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    // to keep searching
16277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    CrashRecoveryContext::Disable();
16377c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    return EXCEPTION_CONTINUE_SEARCH;
16477c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  }
16577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
16677c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // TODO: We can capture the stack backtrace here and store it on the
16777c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // implementation if we so choose.
16877c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
16977c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // Handle the crash
17077c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
17177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
17277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // Note that we don't actually get here because HandleCrash calls
17377c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // longjmp, which means the HandleCrash function never returns.
17477c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  llvm_unreachable("Handled the crash, should have longjmp'ed out of here");
17577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi}
17677c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
17777c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// Because the Enable and Disable calls are static, it means that
17877c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// there may not actually be an Impl available, or even a current
17977c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// CrashRecoveryContext at all.  So we make use of a thread-local
18077c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// exception table.  The handles contained in here will either be
18177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi// non-NULL, valid VEH handles, or NULL.
18277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumistatic sys::ThreadLocal<const void> sCurrentExceptionHandle;
183d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
184a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarvoid CrashRecoveryContext::Enable() {
18563fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  sys::ScopedLock L(*gCrashRecoveryContextMutex);
186c0c815e887d72414894930b62221acc32488c2d0Daniel Dunbar
187a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  if (gCrashRecoveryEnabled)
188a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    return;
189a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
190a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  gCrashRecoveryEnabled = true;
19177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
19277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // We can set up vectored exception handling now.  We will install our
19377c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // handler as the front of the list, though there's no assurances that
19477c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // it will remain at the front (another call could install itself before
19577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  // our handler).  This 1) isn't likely, and 2) shouldn't cause problems.
19677c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  PVOID handle = ::AddVectoredExceptionHandler(1, ExceptionHandler);
19777c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  sCurrentExceptionHandle.set(handle);
198a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
199a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
200a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarvoid CrashRecoveryContext::Disable() {
20163fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  sys::ScopedLock L(*gCrashRecoveryContextMutex);
202c0c815e887d72414894930b62221acc32488c2d0Daniel Dunbar
203a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  if (!gCrashRecoveryEnabled)
204a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    return;
205a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
206a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  gCrashRecoveryEnabled = false;
20777c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
20877c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  PVOID currentHandle = const_cast<PVOID>(sCurrentExceptionHandle.get());
20977c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  if (currentHandle) {
21077c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    // Now we can remove the vectored exception handler from the chain
21177c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    ::RemoveVectoredExceptionHandler(currentHandle);
21277c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi
21377c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    // Reset the handle in our thread-local set.
21477c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi    sCurrentExceptionHandle.set(NULL);
21577c108241aae7d19d9d620b10ced8e783c7c8202NAKAMURA Takumi  }
216a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
217a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
218d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar#else
219d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
220d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// Generic POSIX implementation.
221d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar//
222d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// This implementation relies on synchronous signals being delivered to the
223d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// current thread. We use a thread local object to keep track of the active
224d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// crash recovery context, and install signal handlers to invoke HandleCrash on
225d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// the active object.
226d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar//
227d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// This implementation does not to attempt to chain signal handlers in any
228d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// reliable fashion -- if we get a signal outside of a crash recovery context we
229d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar// simply disable crash recovery and raise the signal again.
230d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
231d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar#include <signal.h>
232d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
233c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic const int Signals[] =
234c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
23563cc2e1982bd02b6484bba3fc0103c688f13711bDaniel Dunbarstatic const unsigned NumSignals = sizeof(Signals) / sizeof(Signals[0]);
23663cc2e1982bd02b6484bba3fc0103c688f13711bDaniel Dunbarstatic struct sigaction PrevActions[NumSignals];
237d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
238d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbarstatic void CrashRecoverySignalHandler(int Signal) {
239d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  // Lookup the current thread local recovery object.
24063fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
241d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
242d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  if (!CRCI) {
243d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // We didn't find a crash recovery context -- this means either we got a
244d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // signal on a thread we didn't expect it on, the application got a signal
245d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // outside of a crash recovery context, or something else went horribly
246d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // wrong.
247d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    //
248d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // Disable crash recovery and raise the signal again. The assumption here is
249d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // that the enclosing application will terminate soon, and we won't want to
250d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // attempt crash recovery again.
251d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    //
252d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    // This call of Disable isn't thread safe, but it doesn't actually matter.
253d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    CrashRecoveryContext::Disable();
254d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    raise(Signal);
255d49e2aa5b89758b3b8841fa427e3c9e90f2e30b2Daniel Dunbar
256d49e2aa5b89758b3b8841fa427e3c9e90f2e30b2Daniel Dunbar    // The signal will be thrown once the signal mask is restored.
257d49e2aa5b89758b3b8841fa427e3c9e90f2e30b2Daniel Dunbar    return;
258d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  }
259d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
260d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  // Unblock the signal we received.
261d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  sigset_t SigMask;
262d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  sigemptyset(&SigMask);
263d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  sigaddset(&SigMask, Signal);
264dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
265d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
266d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  if (CRCI)
267d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
268d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar}
269d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
270d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbarvoid CrashRecoveryContext::Enable() {
27163fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  sys::ScopedLock L(*gCrashRecoveryContextMutex);
272c0c815e887d72414894930b62221acc32488c2d0Daniel Dunbar
273d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  if (gCrashRecoveryEnabled)
274d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    return;
275d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
276d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  gCrashRecoveryEnabled = true;
277d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
278d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  // Setup the signal handler.
279d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  struct sigaction Handler;
280d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  Handler.sa_handler = CrashRecoverySignalHandler;
281d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  Handler.sa_flags = 0;
282d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  sigemptyset(&Handler.sa_mask);
283d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
284d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  for (unsigned i = 0; i != NumSignals; ++i) {
28563cc2e1982bd02b6484bba3fc0103c688f13711bDaniel Dunbar    sigaction(Signals[i], &Handler, &PrevActions[i]);
286d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  }
287d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar}
288d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
289d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbarvoid CrashRecoveryContext::Disable() {
29063fe0669ad5005aacd89f57855d30f905a7dbd92Filip Pizlo  sys::ScopedLock L(*gCrashRecoveryContextMutex);
291c0c815e887d72414894930b62221acc32488c2d0Daniel Dunbar
292d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  if (!gCrashRecoveryEnabled)
293d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar    return;
294d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
295d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  gCrashRecoveryEnabled = false;
296d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
297d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  // Restore the previous signal handlers.
298d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar  for (unsigned i = 0; i != NumSignals; ++i)
299dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    sigaction(Signals[i], &PrevActions[i], nullptr);
300d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar}
301d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
302d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar#endif
303d9082dfd9ab442dd33f552693fcc0f396a514bb6Daniel Dunbar
304dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
305a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  // If crash recovery is disabled, do nothing.
306a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  if (gCrashRecoveryEnabled) {
307a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    assert(!Impl && "Crash recovery context already initialized!");
308a8fa798246503c726b02b415bb1f1b26bc0b0159Daniel Dunbar    CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
309a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    Impl = CRCI;
310a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
311a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    if (setjmp(CRCI->JumpBuffer) != 0) {
312a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar      return false;
313a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar    }
314a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  }
315a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
316dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Fn();
317a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  return true;
318a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
319a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
320a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarvoid CrashRecoveryContext::HandleCrash() {
321a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
322a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  assert(CRCI && "Crash recovery context never initialized!");
323a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  CRCI->HandleCrash();
324a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
325a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar
326a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbarconst std::string &CrashRecoveryContext::getBacktrace() const {
327a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl;
328a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  assert(CRC && "Crash recovery context never initialized!");
329a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  assert(CRC->Failed && "No crash was detected!");
330a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar  return CRC->Backtrace;
331a309dac868e591d7254f570b950a50f640c009f8Daniel Dunbar}
332f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar
333c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines// FIXME: Portability.
334c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic void setThreadBackgroundPriority() {
335c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#ifdef __APPLE__
336c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  setpriority(PRIO_DARWIN_THREAD, 0, PRIO_DARWIN_BG);
337c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#endif
338c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
339c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
340c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic bool hasThreadBackgroundPriority() {
341c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#ifdef __APPLE__
342c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  return getpriority(PRIO_DARWIN_THREAD, 0) == 1;
343c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#else
344c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  return false;
345c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#endif
346c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
347f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar
348f8254d647352f8f194b4753a25d582758289e497Daniel Dunbarnamespace {
349f8254d647352f8f194b4753a25d582758289e497Daniel Dunbarstruct RunSafelyOnThreadInfo {
350dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  function_ref<void()> Fn;
351f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar  CrashRecoveryContext *CRC;
352c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  bool UseBackgroundPriority;
353f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar  bool Result;
354f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar};
355f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar}
356f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar
357f8254d647352f8f194b4753a25d582758289e497Daniel Dunbarstatic void RunSafelyOnThread_Dispatch(void *UserData) {
358f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar  RunSafelyOnThreadInfo *Info =
359f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar    reinterpret_cast<RunSafelyOnThreadInfo*>(UserData);
360c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
361c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (Info->UseBackgroundPriority)
362c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    setThreadBackgroundPriority();
363c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
364dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Info->Result = Info->CRC->RunSafely(Info->Fn);
365f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar}
366dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn,
367f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar                                             unsigned RequestedStackSize) {
368c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  bool UseBackgroundPriority = hasThreadBackgroundPriority();
369c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  RunSafelyOnThreadInfo Info = { Fn, this, UseBackgroundPriority, false };
370f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar  llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize);
3714e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis  if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
3724e91fa3834008778b10d6770f9872c50e1e75659Argyrios Kyrtzidis    CRC->setSwitchedThread();
373f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar  return Info.Result;
374f8254d647352f8f194b4753a25d582758289e497Daniel Dunbar}
375