llvm.org GIT mirror llvm / a309dac
Support: Add CrashRecoveryContext helper object. - Designed as a simple wrapper to allow clients to attempt to catch crashes (memory errors, assertion violations, etc.) and do some kind of recovery. - Currently doesn't actually attempt to catch crashes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@109586 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Dunbar 10 years ago
2 changed file(s) with 170 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===--- CrashRecoveryContext.h - Crash Recovery ----------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
10 #define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
11
12 #include
13
14 namespace llvm {
15 class StringRef;
16
17 /// \brief Crash recovery helper object.
18 ///
19 /// This class implements support for running operations in a safe context so
20 /// that crashes (memory errors, stack overflow, assertion violations) can be
21 /// detected and control restored to the crashing thread. Crash detection is
22 /// purely "best effort", the exact set of failures which can be recovered from
23 /// is platform dependent.
24 ///
25 /// Clients make use of this code by first calling
26 /// CrashRecoveryContext::Enable(), and then executing unsafe operations via a
27 /// CrashRecoveryContext object. For example:
28 ///
29 /// void actual_work(void *);
30 ///
31 /// void foo() {
32 /// CrashRecoveryContext CRC;
33 ///
34 /// if (!CRC.RunSafely(actual_work, 0)) {
35 /// ... a crash was detected, report error to user ...
36 /// }
37 ///
38 /// ... no crash was detected ...
39 /// }
40 ///
41 /// Crash recovery contexts may not be nested.
42 class CrashRecoveryContext {
43 void *Impl;
44
45 public:
46 CrashRecoveryContext() : Impl(0) {}
47 ~CrashRecoveryContext();
48
49 /// \brief Enable crash recovery. This function is not thread safe, clients
50 /// should call it during startup or with a lock held.
51 static void Enable();
52
53 /// \brief Disable crash recovery. This function is not thread safe, clients
54 /// should call it during startup or with a lock held.
55 static void Disable();
56
57 /// \brief Execute the provide callback function (with the given arguments) in
58 /// a protected context.
59 ///
60 /// \return True if the function completed successfully, and false if the
61 /// function crashed (or HandleCrash was called explicitly). Clients should
62 /// make as little assumptions as possible about the program state when
63 /// RunSafely has returned false. Clients can use getBacktrace() to retrieve
64 /// the backtrace of the crash on failures.
65 bool RunSafely(void (*Fn)(void*), void *UserData);
66
67 /// \brief Explicitly trigger a crash recovery in the current process, and
68 /// return failure from RunSafely(). This function does not return.
69 void HandleCrash();
70
71 /// \brief Return a string containing the backtrace where the crash was
72 /// detected; or empty if the backtrace wasn't recovered.
73 ///
74 /// This function is only valid when a crash has been detected (i.e.,
75 /// RunSafely() has returned false.
76 const std::string &getBacktrace() const;
77 };
78
79 }
80
81 #endif
0 //===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Support/CrashRecoveryContext.h"
10 #include "llvm/ADT/SmallString.h"
11 #include
12 using namespace llvm;
13
14 namespace {
15
16 struct CrashRecoveryContextImpl;
17
18 struct CrashRecoveryContextImpl {
19 std::string Backtrace;
20 ::jmp_buf JumpBuffer;
21 volatile unsigned Failed : 1;
22
23 public:
24 CrashRecoveryContextImpl() : Failed(false) {}
25
26 void HandleCrash() {
27 assert(!Failed && "Crash recovery context already failed!");
28 Failed = true;
29
30 // FIXME: Stash the backtrace.
31
32 // Jump back to the RunSafely we were called under.
33 longjmp(JumpBuffer, 1);
34 }
35 };
36
37 }
38
39 static bool gCrashRecoveryEnabled = false;
40
41 CrashRecoveryContext::~CrashRecoveryContext() {
42 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
43 delete CRCI;
44 }
45
46 void CrashRecoveryContext::Enable() {
47 if (gCrashRecoveryEnabled)
48 return;
49
50 gCrashRecoveryEnabled = true;
51 }
52
53 void CrashRecoveryContext::Disable() {
54 if (!gCrashRecoveryEnabled)
55 return;
56
57 gCrashRecoveryEnabled = false;
58 }
59
60 bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) {
61 // If crash recovery is disabled, do nothing.
62 if (gCrashRecoveryEnabled) {
63 assert(!Impl && "Crash recovery context already initialized!");
64 CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl;
65 Impl = CRCI;
66
67 if (setjmp(CRCI->JumpBuffer) != 0) {
68 return false;
69 }
70 }
71
72 Fn(UserData);
73 return true;
74 }
75
76 void CrashRecoveryContext::HandleCrash() {
77 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
78 assert(CRCI && "Crash recovery context never initialized!");
79 CRCI->HandleCrash();
80 }
81
82 const std::string &CrashRecoveryContext::getBacktrace() const {
83 CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl;
84 assert(CRC && "Crash recovery context never initialized!");
85 assert(CRC->Failed && "No crash was detected!");
86 return CRC->Backtrace;
87 }