llvm.org GIT mirror llvm / a4f9839
Augment CrashRecoveryContext to have registered "cleanup" objects that can be used to release resources during a crash. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127849 91177308-0d34-0410-b5e6-96231b3b80d8 Ted Kremenek 9 years ago
2 changed file(s) with 103 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
1414 namespace llvm {
1515 class StringRef;
1616
17 class CrashRecoveryContextCleanup;
18
1719 /// \brief Crash recovery helper object.
1820 ///
1921 /// This class implements support for running operations in a safe context so
4143 /// Crash recovery contexts may not be nested.
4244 class CrashRecoveryContext {
4345 void *Impl;
46 CrashRecoveryContextCleanup *head;
4447
4548 public:
46 CrashRecoveryContext() : Impl(0) {}
49 CrashRecoveryContext() : Impl(0), head(0) {}
4750 ~CrashRecoveryContext();
51
52 void registerCleanup(CrashRecoveryContextCleanup *cleanup);
53 void unregisterCleanup(CrashRecoveryContextCleanup *cleanup);
4854
4955 /// \brief Enable crash recovery.
5056 static void Enable();
8692 const std::string &getBacktrace() const;
8793 };
8894
95 class CrashRecoveryContextCleanup {
96 public:
97 virtual ~CrashRecoveryContextCleanup();
98 virtual void recoverResources() = 0;
99
100 template static CrashRecoveryContextCleanup *create(T *);
101
102 private:
103 friend class CrashRecoveryContext;
104 CrashRecoveryContextCleanup *prev, *next;
105 };
106
107 template
108 class CrashRecoveryContextDestructorCleanup
109 : public CrashRecoveryContextCleanup
110 {
111 T *resource;
112 public:
113 CrashRecoveryContextDestructorCleanup(T *resource) : resource(resource) {}
114 virtual void recoverResources() {
115 resource->~T();
116 }
117 };
118
119 template
120 struct CrashRecoveryContextTrait {
121 static inline CrashRecoveryContextCleanup *createCleanup(T *resource) {
122 return new CrashRecoveryContextDestructorCleanup(resource);
123 }
124 };
125
126 template
127 inline CrashRecoveryContextCleanup* CrashRecoveryContextCleanup::create(T *x) {
128 return CrashRecoveryContext::GetCurrent() ?
129 CrashRecoveryContextTrait::createCleanup(x) :
130 0;
131 }
132
133 class CrashRecoveryContextCleanupRegistrar {
134 CrashRecoveryContext *context;
135 CrashRecoveryContextCleanup *cleanup;
136 public:
137 CrashRecoveryContextCleanupRegistrar(CrashRecoveryContextCleanup *cleanup)
138 : context(CrashRecoveryContext::GetCurrent()),
139 cleanup(cleanup)
140 {
141 if (context && cleanup)
142 context->registerCleanup(cleanup);
143 }
144 ~CrashRecoveryContextCleanupRegistrar() {
145 if (cleanup) {
146 if (context)
147 context->unregisterCleanup(cleanup);
148 else
149 delete cleanup;
150 }
151 }
152 };
89153 }
90154
91155 #endif
5656 static sys::Mutex gCrashRecoveryContexMutex;
5757 static bool gCrashRecoveryEnabled = false;
5858
59 CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
60
5961 CrashRecoveryContext::~CrashRecoveryContext() {
62 // Reclaim registered resources.
63 CrashRecoveryContextCleanup *i = head;
64 while (i) {
65 CrashRecoveryContextCleanup *tmp = i;
66 i = tmp->next;
67 tmp->recoverResources();
68 delete tmp;
69 }
70
6071 CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
6172 delete CRCI;
6273 }
6778 return 0;
6879
6980 return CRCI->CRC;
81 }
82
83 void CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup)
84 {
85 if (!cleanup)
86 return;
87 if (head)
88 head->prev = cleanup;
89 cleanup->next = head;
90 head = cleanup;
91 }
92
93 void
94 CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
95 if (!cleanup)
96 return;
97 if (cleanup == head) {
98 head = cleanup->next;
99 if (head)
100 head->prev = 0;
101 }
102 else {
103 cleanup->prev->next = cleanup->next;
104 if (cleanup->next)
105 cleanup->next->prev = cleanup->prev;
106 }
107 delete cleanup;
70108 }
71109
72110 #ifdef LLVM_ON_WIN32