LLVM  13.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() and llvm_execute_on_thread().
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.
103  void HandleExit(int RetCode);
104 
105  /// Throw again a signal or an exception, after it was catched once by a
106  /// CrashRecoveryContext.
107  static bool throwIfCrash(int RetCode);
108 
109  /// In case of a crash, this is the crash identifier.
110  int RetCode = 0;
111 
112  /// Selects whether handling of failures should be done in the same way as
113  /// for regular crashes. When this is active, a crash would print the
114  /// callstack, clean-up any temporary files and create a coredump/minidump.
116 };
117 
118 /// Abstract base class of cleanup handlers.
119 ///
120 /// Derived classes override method recoverResources, which makes actual work on
121 /// resource recovery.
122 ///
123 /// Cleanup handlers are stored in a double list, which is owned and managed by
124 /// a crash recovery context.
126 protected:
129  : context(context) {}
130 
131 public:
132  bool cleanupFired = false;
133 
135  virtual void recoverResources() = 0;
136 
138  return context;
139  }
140 
141 private:
142  friend class CrashRecoveryContext;
143  CrashRecoveryContextCleanup *prev = nullptr, *next = nullptr;
144 };
145 
146 /// Base class of cleanup handler that controls recovery of resources of the
147 /// given type.
148 ///
149 /// \tparam Derived Class that uses this class as a base.
150 /// \tparam T Type of controlled resource.
151 ///
152 /// This class serves as a base for its template parameter as implied by
153 /// Curiously Recurring Template Pattern.
154 ///
155 /// This class factors out creation of a cleanup handler. The latter requires
156 /// knowledge of the current recovery context, which is provided by this class.
157 template<typename Derived, typename T>
159 protected:
163 
164 public:
165  /// Creates cleanup handler.
166  /// \param x Pointer to the resource recovered by this handler.
167  /// \return New handler or null if the method was called outside a recovery
168  /// context.
169  static Derived *create(T *x) {
170  if (x) {
172  return new Derived(context, x);
173  }
174  return nullptr;
175  }
176 };
177 
178 /// Cleanup handler that reclaims resource by calling destructor on it.
179 template <typename T>
181  CrashRecoveryContextCleanupBase<CrashRecoveryContextDestructorCleanup<T>, T> {
182 public:
184  T *resource)
187 
188  void recoverResources() override {
189  this->resource->~T();
190  }
191 };
192 
193 /// Cleanup handler that reclaims resource by calling 'delete' on it.
194 template <typename T>
196  CrashRecoveryContextCleanupBase<CrashRecoveryContextDeleteCleanup<T>, T> {
197 public:
201 
202  void recoverResources() override { delete this->resource; }
203 };
204 
205 /// Cleanup handler that reclaims resource by calling its method 'Release'.
206 template <typename T>
208  CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T> {
209 public:
211  T *resource)
213  T>(context, resource) {}
214 
215  void recoverResources() override { this->resource->Release(); }
216 };
217 
218 /// Helper class for managing resource cleanups.
219 ///
220 /// \tparam T Type of resource been reclaimed.
221 /// \tparam Cleanup Class that defines how the resource is reclaimed.
222 ///
223 /// Clients create objects of this type in the code executed in a crash recovery
224 /// context to ensure that the resource will be reclaimed even in the case of
225 /// crash. For example:
226 ///
227 /// \code
228 /// void actual_work(void *) {
229 /// ...
230 /// std::unique_ptr<Resource> R(new Resource());
231 /// CrashRecoveryContextCleanupRegistrar D(R.get());
232 /// ...
233 /// }
234 ///
235 /// void foo() {
236 /// CrashRecoveryContext CRC;
237 ///
238 /// if (!CRC.RunSafely(actual_work, 0)) {
239 /// ... a crash was detected, report error to user ...
240 /// }
241 /// \endcode
242 ///
243 /// If the code of `actual_work` in the example above does not crash, the
244 /// destructor of CrashRecoveryContextCleanupRegistrar removes cleanup code from
245 /// the current CrashRecoveryContext and the resource is reclaimed by the
246 /// destructor of std::unique_ptr. If crash happens, destructors are not called
247 /// and the resource is reclaimed by cleanup object registered in the recovery
248 /// context by the constructor of CrashRecoveryContextCleanupRegistrar.
249 template <typename T, typename Cleanup = CrashRecoveryContextDeleteCleanup<T> >
252 
253 public:
255  : cleanup(Cleanup::create(x)) {
256  if (cleanup)
257  cleanup->getContext()->registerCleanup(cleanup);
258  }
259 
261 
262  void unregister() {
263  if (cleanup && !cleanup->cleanupFired)
264  cleanup->getContext()->unregisterCleanup(cleanup);
265  cleanup = nullptr;
266  }
267 };
268 } // end namespace llvm
269 
270 #endif // LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
llvm::CrashRecoveryContext::Enable
static void Enable()
Enable crash recovery.
Definition: CrashRecoveryContext.cpp:138
llvm::CrashRecoveryContextDestructorCleanup::recoverResources
void recoverResources() override
Definition: CrashRecoveryContext.h:188
llvm
This class represents lattice values for constants.
Definition: AllocatorList.h:23
llvm::CrashRecoveryContextDeleteCleanup::recoverResources
void recoverResources() override
Definition: CrashRecoveryContext.h:202
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:183
llvm::CrashRecoveryContextCleanup::getContext
CrashRecoveryContext * getContext() const
Definition: CrashRecoveryContext.h:137
llvm::CrashRecoveryContext::RunSafely
bool RunSafely(void(*Fn)(void *), void *UserData)
Definition: CrashRecoveryContext.h:82
llvm::CrashRecoveryContextCleanupRegistrar::~CrashRecoveryContextCleanupRegistrar
~CrashRecoveryContextCleanupRegistrar()
Definition: CrashRecoveryContext.h:260
llvm::CrashRecoveryContextDestructorCleanup
Cleanup handler that reclaims resource by calling destructor on it.
Definition: CrashRecoveryContext.h:180
llvm::CrashRecoveryContextCleanupBase::CrashRecoveryContextCleanupBase
CrashRecoveryContextCleanupBase(CrashRecoveryContext *context, T *resource)
Definition: CrashRecoveryContext.h:161
llvm::CrashRecoveryContext::RetCode
int RetCode
In case of a crash, this is the crash identifier.
Definition: CrashRecoveryContext.h:110
llvm::CrashRecoveryContextCleanupBase
Base class of cleanup handler that controls recovery of resources of the given type.
Definition: CrashRecoveryContext.h:158
cleanup
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
Definition: BlockFrequencyInfoImpl.cpp:288
llvm::CrashRecoveryContext::registerCleanup
void registerCleanup(CrashRecoveryContextCleanup *cleanup)
Register cleanup handler, which is used when the recovery context is finished.
Definition: CrashRecoveryContext.cpp:155
llvm::CrashRecoveryContext::~CrashRecoveryContext
~CrashRecoveryContext()
Definition: CrashRecoveryContext.cpp:105
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:198
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:411
llvm::CrashRecoveryContext::HandleExit
LLVM_ATTRIBUTE_NORETURN void HandleExit(int RetCode)
Explicitly trigger a crash recovery in the current process, and return failure from RunSafely().
Definition: CrashRecoveryContext.cpp:431
llvm::CrashRecoveryContext::Disable
static void Disable()
Disable crash recovery.
Definition: CrashRecoveryContext.cpp:147
llvm::CrashRecoveryContext::isRecoveringFromCrash
static bool isRecoveringFromCrash()
Return true if the current thread is recovering from a crash.
Definition: CrashRecoveryContext.cpp:123
llvm::CrashRecoveryContextCleanupRegistrar::unregister
void unregister()
Definition: CrashRecoveryContext.h:262
llvm::CrashRecoveryContextCleanup::CrashRecoveryContextCleanup
CrashRecoveryContextCleanup(CrashRecoveryContext *context)
Definition: CrashRecoveryContext.h:128
llvm::CrashRecoveryContext::DumpStackAndCleanupOnFailure
bool DumpStackAndCleanupOnFailure
Selects whether handling of failures should be done in the same way as for regular crashes.
Definition: CrashRecoveryContext.h:115
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:176
llvm::CrashRecoveryContextCleanup
Abstract base class of cleanup handlers.
Definition: CrashRecoveryContext.h:125
llvm::CrashRecoveryContextReleaseRefCleanup
Cleanup handler that reclaims resource by calling its method 'Release'.
Definition: CrashRecoveryContext.h:207
llvm::CrashRecoveryContextReleaseRefCleanup::CrashRecoveryContextReleaseRefCleanup
CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context, T *resource)
Definition: CrashRecoveryContext.h:210
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:127
llvm::CrashRecoveryContextCleanupBase::create
static Derived * create(T *x)
Creates cleanup handler.
Definition: CrashRecoveryContext.h:169
LLVM_ATTRIBUTE_NORETURN
#define LLVM_ATTRIBUTE_NORETURN
Definition: Compiler.h:249
llvm::CrashRecoveryContextCleanupBase::resource
T * resource
Definition: CrashRecoveryContext.h:160
llvm::CrashRecoveryContextCleanupRegistrar::CrashRecoveryContextCleanupRegistrar
CrashRecoveryContextCleanupRegistrar(T *x)
Definition: CrashRecoveryContext.h:254
x
TODO unsigned x
Definition: README.txt:10
llvm::CrashRecoveryContextDeleteCleanup
Cleanup handler that reclaims resource by calling 'delete' on it.
Definition: CrashRecoveryContext.h:195
llvm::CrashRecoveryContextCleanupRegistrar
Helper class for managing resource cleanups.
Definition: CrashRecoveryContext.h:250
llvm::CrashRecoveryContext::unregisterCleanup
void unregisterCleanup(CrashRecoveryContextCleanup *cleanup)
Definition: CrashRecoveryContext.cpp:166
llvm::CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup
virtual ~CrashRecoveryContextCleanup()
Definition: CrashRecoveryContext.cpp:96
llvm::CrashRecoveryContext
Crash recovery helper object.
Definition: CrashRecoveryContext.h:46
llvm::CrashRecoveryContext::CrashRecoveryContext
CrashRecoveryContext()
Definition: CrashRecoveryContext.cpp:98
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:132
llvm::CrashRecoveryContextReleaseRefCleanup::recoverResources
void recoverResources() override
Definition: CrashRecoveryContext.h:215
llvm::CrashRecoveryContextCleanup::context
CrashRecoveryContext * context
Definition: CrashRecoveryContext.h:127