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