LLVM  14.0.0git
CrashRecoveryContext.h
Go to the documentation of this file.
1 //===--- CrashRecoveryContext.h - Crash Recovery ----------------*- C++ -*-===//
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 
9 #ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
10 #define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
11 
12 #include "llvm/ADT/STLExtras.h"
13 
14 namespace llvm {
15 class CrashRecoveryContextCleanup;
16 
17 /// 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 /// \code
30 /// void actual_work(void *);
31 ///
32 /// void foo() {
33 /// CrashRecoveryContext CRC;
34 ///
35 /// if (!CRC.RunSafely(actual_work, 0)) {
36 /// ... a crash was detected, report error to user ...
37 /// }
38 ///
39 /// ... no crash was detected ...
40 /// }
41 /// \endcode
42 ///
43 /// To assist recovery the class allows specifying set of actions that will be
44 /// executed in any case, whether crash occurs or not. These actions may be used
45 /// to reclaim resources in the case of crash.
47  void *Impl = nullptr;
48  CrashRecoveryContextCleanup *head = nullptr;
49 
50 public:
53 
54  /// Register cleanup handler, which is used when the recovery context is
55  /// finished.
56  /// The recovery context owns the handler.
58 
60 
61  /// Enable crash recovery.
62  static void Enable();
63 
64  /// Disable crash recovery.
65  static void Disable();
66 
67  /// Return the active context, if the code is currently executing in a
68  /// thread which is in a protected context.
70 
71  /// Return true if the current thread is recovering from a crash.
72  static bool isRecoveringFromCrash();
73 
74  /// Execute the provided callback function (with the given arguments) in
75  /// a protected context.
76  ///
77  /// \return True if the function completed successfully, and false if the
78  /// function crashed (or HandleCrash was called explicitly). Clients should
79  /// make as little assumptions as possible about the program state when
80  /// RunSafely has returned false.
81  bool RunSafely(function_ref<void()> Fn);
82  bool RunSafely(void (*Fn)(void*), void *UserData) {
83  return RunSafely([&]() { Fn(UserData); });
84  }
85 
86  /// Execute the provide callback function (with the given arguments) in
87  /// a protected context which is run in another thread (optionally with a
88  /// requested stack size).
89  ///
90  /// See RunSafely().
91  ///
92  /// On Darwin, if PRIO_DARWIN_BG is set on the calling thread, it will be
93  /// propagated to the new thread as well.
94  bool RunSafelyOnThread(function_ref<void()>, unsigned RequestedStackSize = 0);
95  bool RunSafelyOnThread(void (*Fn)(void*), void *UserData,
96  unsigned RequestedStackSize = 0) {
97  return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize);
98  }
99 
100  /// Explicitly trigger a crash recovery in the current process, and
101  /// return failure from RunSafely(). This function does not return.
102  [[noreturn]] void HandleExit(int RetCode);
103 
104  /// Throw again a signal or an exception, after it was catched once by a
105  /// CrashRecoveryContext.
106  static bool throwIfCrash(int RetCode);
107 
108  /// In case of a crash, this is the crash identifier.
109  int RetCode = 0;
110 
111  /// Selects whether handling of failures should be done in the same way as
112  /// for regular crashes. When this is active, a crash would print the
113  /// callstack, clean-up any temporary files and create a coredump/minidump.
115 };
116 
117 /// Abstract base class of cleanup handlers.
118 ///
119 /// Derived classes override method recoverResources, which makes actual work on
120 /// resource recovery.
121 ///
122 /// Cleanup handlers are stored in a double list, which is owned and managed by
123 /// a crash recovery context.
125 protected:
128  : context(context) {}
129 
130 public:
131  bool cleanupFired = false;
132 
134  virtual void recoverResources() = 0;
135 
137  return context;
138  }
139 
140 private:
141  friend class CrashRecoveryContext;
142  CrashRecoveryContextCleanup *prev = nullptr, *next = nullptr;
143 };
144 
145 /// Base class of cleanup handler that controls recovery of resources of the
146 /// given type.
147 ///
148 /// \tparam Derived Class that uses this class as a base.
149 /// \tparam T Type of controlled resource.
150 ///
151 /// This class serves as a base for its template parameter as implied by
152 /// Curiously Recurring Template Pattern.
153 ///
154 /// This class factors out creation of a cleanup handler. The latter requires
155 /// knowledge of the current recovery context, which is provided by this class.
156 template<typename Derived, typename T>
158 protected:
162 
163 public:
164  /// Creates cleanup handler.
165  /// \param x Pointer to the resource recovered by this handler.
166  /// \return New handler or null if the method was called outside a recovery
167  /// context.
168  static Derived *create(T *x) {
169  if (x) {
171  return new Derived(context, x);
172  }
173  return nullptr;
174  }
175 };
176 
177 /// Cleanup handler that reclaims resource by calling destructor on it.
178 template <typename T>
180  CrashRecoveryContextCleanupBase<CrashRecoveryContextDestructorCleanup<T>, T> {
181 public:
183  T *resource)
186 
187  void recoverResources() override {
188  this->resource->~T();
189  }
190 };
191 
192 /// Cleanup handler that reclaims resource by calling 'delete' on it.
193 template <typename T>
195  CrashRecoveryContextCleanupBase<CrashRecoveryContextDeleteCleanup<T>, T> {
196 public:
200 
201  void recoverResources() override { delete this->resource; }
202 };
203 
204 /// Cleanup handler that reclaims resource by calling its method 'Release'.
205 template <typename T>
207  CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T> {
208 public:
210  T *resource)
212  T>(context, resource) {}
213 
214  void recoverResources() override { this->resource->Release(); }
215 };
216 
217 /// Helper class for managing resource cleanups.
218 ///
219 /// \tparam T Type of resource been reclaimed.
220 /// \tparam Cleanup Class that defines how the resource is reclaimed.
221 ///
222 /// Clients create objects of this type in the code executed in a crash recovery
223 /// context to ensure that the resource will be reclaimed even in the case of
224 /// crash. For example:
225 ///
226 /// \code
227 /// void actual_work(void *) {
228 /// ...
229 /// std::unique_ptr<Resource> R(new Resource());
230 /// CrashRecoveryContextCleanupRegistrar D(R.get());
231 /// ...
232 /// }
233 ///
234 /// void foo() {
235 /// CrashRecoveryContext CRC;
236 ///
237 /// if (!CRC.RunSafely(actual_work, 0)) {
238 /// ... a crash was detected, report error to user ...
239 /// }
240 /// \endcode
241 ///
242 /// If the code of `actual_work` in the example above does not crash, the
243 /// destructor of CrashRecoveryContextCleanupRegistrar removes cleanup code from
244 /// the current CrashRecoveryContext and the resource is reclaimed by the
245 /// destructor of std::unique_ptr. If crash happens, destructors are not called
246 /// and the resource is reclaimed by cleanup object registered in the recovery
247 /// context by the constructor of CrashRecoveryContextCleanupRegistrar.
248 template <typename T, typename Cleanup = CrashRecoveryContextDeleteCleanup<T> >
251 
252 public:
254  : cleanup(Cleanup::create(x)) {
255  if (cleanup)
256  cleanup->getContext()->registerCleanup(cleanup);
257  }
258 
260 
261  void unregister() {
262  if (cleanup && !cleanup->cleanupFired)
263  cleanup->getContext()->unregisterCleanup(cleanup);
264  cleanup = nullptr;
265  }
266 };
267 } // end namespace llvm
268 
269 #endif // LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
llvm::CrashRecoveryContext::Enable
static void Enable()
Enable crash recovery.
Definition: CrashRecoveryContext.cpp:139
llvm::CrashRecoveryContextDestructorCleanup::recoverResources
void recoverResources() override
Definition: CrashRecoveryContext.h:187
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::CrashRecoveryContextDeleteCleanup::recoverResources
void recoverResources() override
Definition: CrashRecoveryContext.h:201
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
llvm::CrashRecoveryContextDestructorCleanup::CrashRecoveryContextDestructorCleanup
CrashRecoveryContextDestructorCleanup(CrashRecoveryContext *context, T *resource)
Definition: CrashRecoveryContext.h:182
llvm::CrashRecoveryContextCleanup::getContext
CrashRecoveryContext * getContext() const
Definition: CrashRecoveryContext.h:136
T
llvm::CrashRecoveryContext::RunSafely
bool RunSafely(void(*Fn)(void *), void *UserData)
Definition: CrashRecoveryContext.h:82
llvm::CrashRecoveryContextCleanupRegistrar::~CrashRecoveryContextCleanupRegistrar
~CrashRecoveryContextCleanupRegistrar()
Definition: CrashRecoveryContext.h:259
llvm::CrashRecoveryContextDestructorCleanup
Cleanup handler that reclaims resource by calling destructor on it.
Definition: CrashRecoveryContext.h:179
llvm::CrashRecoveryContextCleanupBase::CrashRecoveryContextCleanupBase
CrashRecoveryContextCleanupBase(CrashRecoveryContext *context, T *resource)
Definition: CrashRecoveryContext.h:160
llvm::CrashRecoveryContext::RetCode
int RetCode
In case of a crash, this is the crash identifier.
Definition: CrashRecoveryContext.h:109
llvm::CrashRecoveryContextCleanupBase
Base class of cleanup handler that controls recovery of resources of the given type.
Definition: CrashRecoveryContext.h:157
cleanup
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
Definition: BlockFrequencyInfoImpl.cpp:304
llvm::CrashRecoveryContext::registerCleanup
void registerCleanup(CrashRecoveryContextCleanup *cleanup)
Register cleanup handler, which is used when the recovery context is finished.
Definition: CrashRecoveryContext.cpp:156
llvm::CrashRecoveryContext::~CrashRecoveryContext
~CrashRecoveryContext()
Definition: CrashRecoveryContext.cpp:106
T
#define T
Definition: Mips16ISelLowering.cpp:341
STLExtras.h
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
llvm::CrashRecoveryContextCleanup::recoverResources
virtual void recoverResources()=0
llvm::CrashRecoveryContextDeleteCleanup::CrashRecoveryContextDeleteCleanup
CrashRecoveryContextDeleteCleanup(CrashRecoveryContext *context, T *resource)
Definition: CrashRecoveryContext.h:197
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::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
llvm::CrashRecoveryContextCleanupRegistrar::unregister
void unregister()
Definition: CrashRecoveryContext.h:261
llvm::CrashRecoveryContextCleanup::CrashRecoveryContextCleanup
CrashRecoveryContextCleanup(CrashRecoveryContext *context)
Definition: CrashRecoveryContext.h:127
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
llvm::CrashRecoveryContextReleaseRefCleanup
Cleanup handler that reclaims resource by calling its method 'Release'.
Definition: CrashRecoveryContext.h:206
llvm::CrashRecoveryContextReleaseRefCleanup::CrashRecoveryContextReleaseRefCleanup
CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context, T *resource)
Definition: CrashRecoveryContext.h:209
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::CrashRecoveryContextCleanupBase::create
static Derived * create(T *x)
Creates cleanup handler.
Definition: CrashRecoveryContext.h:168
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::CrashRecoveryContextCleanupBase::resource
T * resource
Definition: CrashRecoveryContext.h:159
llvm::CrashRecoveryContextCleanupRegistrar::CrashRecoveryContextCleanupRegistrar
CrashRecoveryContextCleanupRegistrar(T *x)
Definition: CrashRecoveryContext.h:253
x
TODO unsigned x
Definition: README.txt:10
llvm::CrashRecoveryContextDeleteCleanup
Cleanup handler that reclaims resource by calling 'delete' on it.
Definition: CrashRecoveryContext.h:194
llvm::CrashRecoveryContextCleanupRegistrar
Helper class for managing resource cleanups.
Definition: CrashRecoveryContext.h:249
llvm::CrashRecoveryContext::unregisterCleanup
void unregisterCleanup(CrashRecoveryContextCleanup *cleanup)
Definition: CrashRecoveryContext.cpp:167
llvm::CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup
virtual ~CrashRecoveryContextCleanup()
Definition: CrashRecoveryContext.cpp:97
llvm::CrashRecoveryContext
Crash recovery helper object.
Definition: CrashRecoveryContext.h:46
llvm::CrashRecoveryContext::CrashRecoveryContext
CrashRecoveryContext()
Definition: CrashRecoveryContext.cpp:99
llvm::CrashRecoveryContext::RunSafelyOnThread
bool RunSafelyOnThread(void(*Fn)(void *), void *UserData, unsigned RequestedStackSize=0)
Definition: CrashRecoveryContext.h:95
llvm::CrashRecoveryContextCleanup::cleanupFired
bool cleanupFired
Definition: CrashRecoveryContext.h:131
llvm::CrashRecoveryContextReleaseRefCleanup::recoverResources
void recoverResources() override
Definition: CrashRecoveryContext.h:214
llvm::CrashRecoveryContextCleanup::context
CrashRecoveryContext * context
Definition: CrashRecoveryContext.h:126