llvm.org GIT mirror llvm / 6dbdbdd
Updated docs in CrashRecoveryContext.h Differential Revision: https://reviews.llvm.org/D43200 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326763 91177308-0d34-0410-b5e6-96231b3b80d8 Serge Pavlov 2 years ago
1 changed file(s) with 78 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
1414 namespace llvm {
1515 class CrashRecoveryContextCleanup;
1616
17 /// \brief Crash recovery helper object.
17 /// Crash recovery helper object.
1818 ///
1919 /// This class implements support for running operations in a safe context so
2020 /// that crashes (memory errors, stack overflow, assertion violations) can be
2626 /// CrashRecoveryContext::Enable(), and then executing unsafe operations via a
2727 /// CrashRecoveryContext object. For example:
2828 ///
29 /// \code
2930 /// void actual_work(void *);
3031 ///
3132 /// void foo() {
3738 ///
3839 /// ... no crash was detected ...
3940 /// }
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.
4046 class CrashRecoveryContext {
4147 void *Impl;
4248 CrashRecoveryContextCleanup *head;
4551 CrashRecoveryContext() : Impl(nullptr), head(nullptr) {}
4652 ~CrashRecoveryContext();
4753
54 /// Register cleanup handler, which is used when the recovery context is
55 /// finished.
56 /// The recovery context owns the the handler.
4857 void registerCleanup(CrashRecoveryContextCleanup *cleanup);
58
4959 void unregisterCleanup(CrashRecoveryContextCleanup *cleanup);
5060
51 /// \brief Enable crash recovery.
61 /// Enable crash recovery.
5262 static void Enable();
5363
54 /// \brief Disable crash recovery.
64 /// Disable crash recovery.
5565 static void Disable();
5666
57 /// \brief Return the active context, if the code is currently executing in a
67 /// Return the active context, if the code is currently executing in a
5868 /// thread which is in a protected context.
5969 static CrashRecoveryContext *GetCurrent();
6070
61 /// \brief Return true if the current thread is recovering from a
62 /// crash.
71 /// Return true if the current thread is recovering from a crash.
6372 static bool isRecoveringFromCrash();
6473
65 /// \brief Execute the provide callback function (with the given arguments) in
74 /// Execute the provided callback function (with the given arguments) in
6675 /// a protected context.
6776 ///
6877 /// \return True if the function completed successfully, and false if the
7483 return RunSafely([&]() { Fn(UserData); });
7584 }
7685
77 /// \brief Execute the provide callback function (with the given arguments) in
86 /// Execute the provide callback function (with the given arguments) in
7887 /// a protected context which is run in another thread (optionally with a
7988 /// requested stack size).
8089 ///
8897 return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize);
8998 }
9099
91 /// \brief Explicitly trigger a crash recovery in the current process, and
100 /// Explicitly trigger a crash recovery in the current process, and
92101 /// return failure from RunSafely(). This function does not return.
93102 void HandleCrash();
94103 };
95104
105 /// Abstract base class of cleanup handlers.
106 ///
107 /// Derived classes override method recoverResources, which makes actual work on
108 /// resource recovery.
109 ///
110 /// Cleanup handlers are stored in a double list, which is owned and managed by
111 /// a crash recovery context.
96112 class CrashRecoveryContextCleanup {
97113 protected:
98114 CrashRecoveryContext *context;
114130 CrashRecoveryContextCleanup *prev, *next;
115131 };
116132
117 template
133 /// Base class of cleanup handler that controls recovery of resources of the
134 /// given type.
135 ///
136 /// \tparam Derived Class that uses this class as a base.
137 /// \tparam T Type of controlled resource.
138 ///
139 /// This class serves as a base for its template parameter as implied by
140 /// Curiously Recurring Template Pattern.
141 ///
142 /// This class factors out creation of a cleanup handler. The latter requires
143 /// knowledge of the current recovery context, which is provided by this class.
144 template
118145 class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup {
119146 protected:
120147 T *resource;
122149 : CrashRecoveryContextCleanup(context), resource(resource) {}
123150
124151 public:
125 static DERIVED *create(T *x) {
152 /// Creates cleanup handler.
153 /// \param x Pointer to the resource recovered by this handler.
154 /// \return New handler or null if the method was called outside a recovery
155 /// context.
156 static Derived *create(T *x) {
126157 if (x) {
127158 if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent())
128 return new DERIVED(context, x);
159 return new Derived(context, x);
129160 }
130161 return nullptr;
131162 }
132163 };
133164
165 /// Cleanup handler that reclaims resource by calling destructor on it.
134166 template
135167 class CrashRecoveryContextDestructorCleanup : public
136168 CrashRecoveryContextCleanupBase, T> {
145177 }
146178 };
147179
180 /// Cleanup handler that reclaims resource by calling 'delete' on it.
148181 template
149182 class CrashRecoveryContextDeleteCleanup : public
150183 CrashRecoveryContextCleanupBase, T> {
156189 void recoverResources() override { delete this->resource; }
157190 };
158191
192 /// Cleanup handler that reclaims resource by calling its method 'Release'.
159193 template
160194 class CrashRecoveryContextReleaseRefCleanup : public
161 CrashRecoveryContextCleanupBase, T>
162 {
195 CrashRecoveryContextCleanupBase, T> {
163196 public:
164197 CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context,
165198 T *resource)
169202 void recoverResources() override { this->resource->Release(); }
170203 };
171204
205 /// Helper class for managing resource cleanups.
206 ///
207 /// \tparam T Type of resource been reclaimed.
208 /// \tparam Cleanup Class that defines how the resource is reclaimed.
209 ///
210 /// Clients create objects of this type in the code executed in a crash recovery
211 /// context to ensure that the resource will be reclaimed even in the case of
212 /// crash. For example:
213 ///
214 /// \code
215 /// void actual_work(void *) {
216 /// ...
217 /// std::unique_ptr R(new Resource());
218 /// CrashRecoveryContextCleanupRegistrar D(R.get());
219 /// ...
220 /// }
221 ///
222 /// void foo() {
223 /// CrashRecoveryContext CRC;
224 ///
225 /// if (!CRC.RunSafely(actual_work, 0)) {
226 /// ... a crash was detected, report error to user ...
227 /// }
228 /// \endcode
229 ///
230 /// If the code of `actual_work` in the example above does not crash, the
231 /// destructor of CrashRecoveryContextCleanupRegistrar removes cleanup code from
232 /// the current CrashRecoveryContext and the resource is reclaimed by the
233 /// destructor of std::unique_ptr. If crash happens, destructors are not called
234 /// and the resource is reclaimed by cleanup object registered in the recovery
235 /// context by the constructor of CrashRecoveryContextCleanupRegistrar.
172236 template >
173237 class CrashRecoveryContextCleanupRegistrar {
174238 CrashRecoveryContextCleanup *cleanup;