blob: 870221e1711285d643a4c2ffbf297b325de2130c [file] [log] [blame]
Daniel Dunbara309dac2010-07-28 15:40:20 +00001//===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/CrashRecoveryContext.h"
11#include "llvm/ADT/SmallString.h"
12#include <setjmp.h>
13using namespace llvm;
14
15namespace {
16
17struct CrashRecoveryContextImpl;
18
19struct CrashRecoveryContextImpl {
20 std::string Backtrace;
21 ::jmp_buf JumpBuffer;
22 volatile unsigned Failed : 1;
23
24public:
25 CrashRecoveryContextImpl() : Failed(false) {}
26
27 void HandleCrash() {
28 assert(!Failed && "Crash recovery context already failed!");
29 Failed = true;
30
31 // FIXME: Stash the backtrace.
32
33 // Jump back to the RunSafely we were called under.
34 longjmp(JumpBuffer, 1);
35 }
36};
37
38}
39
40static bool gCrashRecoveryEnabled = false;
41
42CrashRecoveryContext::~CrashRecoveryContext() {
43 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
44 delete CRCI;
45}
46
47void CrashRecoveryContext::Enable() {
48 if (gCrashRecoveryEnabled)
49 return;
50
51 gCrashRecoveryEnabled = true;
52}
53
54void CrashRecoveryContext::Disable() {
55 if (!gCrashRecoveryEnabled)
56 return;
57
58 gCrashRecoveryEnabled = false;
59}
60
61bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) {
62 // If crash recovery is disabled, do nothing.
63 if (gCrashRecoveryEnabled) {
64 assert(!Impl && "Crash recovery context already initialized!");
65 CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl;
66 Impl = CRCI;
67
68 if (setjmp(CRCI->JumpBuffer) != 0) {
69 return false;
70 }
71 }
72
73 Fn(UserData);
74 return true;
75}
76
77void CrashRecoveryContext::HandleCrash() {
78 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
79 assert(CRCI && "Crash recovery context never initialized!");
80 CRCI->HandleCrash();
81}
82
83const std::string &CrashRecoveryContext::getBacktrace() const {
84 CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl;
85 assert(CRC && "Crash recovery context never initialized!");
86 assert(CRC->Failed && "No crash was detected!");
87 return CRC->Backtrace;
88}