42cf5bc1 |
1 | // Created on: 1992-09-28 |
2 | // Created by: Ramin BARRETO |
3 | // Copyright (c) 1992-1999 Matra Datavision |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
5 | // |
6 | // This file is part of Open CASCADE Technology software library. |
7 | // |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
13 | // |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
16 | |
17 | #ifndef _Standard_ErrorHandler_HeaderFile |
18 | #define _Standard_ErrorHandler_HeaderFile |
19 | |
20 | #include <Standard.hxx> |
42cf5bc1 |
21 | #include <Standard_Handle.hxx> |
22 | |
23 | #include <Standard_PErrorHandler.hxx> |
24 | #include <Standard_JmpBuf.hxx> |
25 | #include <Standard_HandlerStatus.hxx> |
26 | #include <Standard_ThreadId.hxx> |
42cf5bc1 |
27 | #include <Standard_Type.hxx> |
c9246067 |
28 | |
29 | //! @file |
30 | //! Support of handling of C signals as C++-style exceptions, and implementation |
31 | //! of C++ exception handling on platforms that do not implement these natively. |
32 | //! |
33 | //! The implementation is based on C long jumps. |
34 | //! |
c9246067 |
35 | //! If macro OCC_CONVERT_SIGNALS is defined, this enables macro OCC_CATCH_SIGNALS |
36 | //! that can be used in the code (often inside try {} blocks) to convert C-style |
37 | //! signals to standard C++ exceptions. This works only when OSD::SetSignal() |
38 | //! is called to set appropriate signal handler. In the case of signal (like |
39 | //! access violation, division by zero, etc.) it will jump to the nearest |
40 | //! OCC_CATCH_SIGNALS in the call stack, which will then throw a C++ exception. |
41 | //! This method is useful for Unix and Linux systems where C++ exceptions |
42 | //! cannot be thrown from C signal handler. |
43 | //! |
44 | //! On Windows with MSVC compiler, exceptions can be thrown directly from |
45 | //! signal handler, this OCC_CONVERT_SIGNALS is not needed. Note however that |
46 | //! this requires that compiler option /EHa is used. |
47 | |
9775fa61 |
48 | #if defined(OCC_CONVERT_SIGNALS) |
c9246067 |
49 | |
50 | // Exceptions are raied as usual, signal cause jumps in the nearest |
51 | // OCC_CATCH_SIGNALS and then thrown as exceptions. |
52 | #define OCC_CATCH_SIGNALS Standard_ErrorHandler _aHandler; \ |
53 | if(setjmp(_aHandler.Label())) { \ |
54 | _aHandler.Catches(STANDARD_TYPE(Standard_Failure)); \ |
55 | _aHandler.Error()->Reraise(); \ |
56 | } |
57 | |
6fab2d4f |
58 | // Suppress GCC warning "variable ... might be clobbered by 'longjmp' or 'vfork'" |
f2139a7f |
59 | #if defined(__GNUC__) && ! defined(__INTEL_COMPILER) && ! defined(__clang__) |
6fab2d4f |
60 | #pragma GCC diagnostic ignored "-Wclobbered" |
61 | #endif |
62 | |
c9246067 |
63 | #else |
64 | |
65 | // Normal Exceptions (for example WNT with MSVC and option /GHa) |
66 | #define OCC_CATCH_SIGNALS |
67 | |
68 | #endif |
69 | |
42cf5bc1 |
70 | class Standard_Failure; |
42cf5bc1 |
71 | |
c9246067 |
72 | //! Class implementing mechanics of conversion of signals to exceptions. |
73 | //! |
74 | //! Each instance of it stores data for jump placement, thread id, |
75 | //! and callbacks to be called during jump (for proper resource release). |
76 | //! |
77 | //! The active handlers are stored in the global stack, which is used |
78 | //! to find appropriate handler when signal is raised. |
42cf5bc1 |
79 | |
80 | class Standard_ErrorHandler |
81 | { |
82 | public: |
83 | |
84 | DEFINE_STANDARD_ALLOC |
85 | |
86 | |
87 | //! Create a ErrorHandler (to be used with try{}catch(){}). |
88 | //! It uses the "setjmp" and "longjmp" routines. |
89 | Standard_EXPORT Standard_ErrorHandler(); |
90 | |
91 | //! Unlinks and checks if there is a raised exception. |
92 | Standard_EXPORT void Destroy(); |
c9246067 |
93 | |
94 | //! Destructor |
95 | ~Standard_ErrorHandler() |
96 | { |
97 | Destroy(); |
98 | } |
42cf5bc1 |
99 | |
100 | //! Removes handler from the handlers list |
101 | Standard_EXPORT void Unlink(); |
102 | |
103 | //! Returns "True" if the caught exception has the same type |
104 | //! or inherits from "aType" |
105 | Standard_EXPORT Standard_Boolean Catches (const Handle(Standard_Type)& aType); |
106 | |
107 | //! Returns label for jump |
c9246067 |
108 | Standard_JmpBuf& Label() { return myLabel; } |
42cf5bc1 |
109 | |
110 | //! Returns the current Error. |
111 | Standard_EXPORT Handle(Standard_Failure) Error() const; |
112 | |
113 | //! Returns the caught exception. |
114 | Standard_EXPORT static Handle(Standard_Failure) LastCaughtError(); |
115 | |
116 | //! Test if the code is currently running in a try block |
117 | Standard_EXPORT static Standard_Boolean IsInTryBlock(); |
118 | |
42cf5bc1 |
119 | private: |
42cf5bc1 |
120 | |
121 | //! A exception is raised but it is not yet caught. |
122 | //! So Abort the current function and transmit the exception |
123 | //! to "calling routines". |
124 | //! Warning: If no catch is prepared for this exception, it displays the |
125 | //! exception name and calls "exit(1)". |
126 | Standard_EXPORT static void Abort (const Handle(Standard_Failure)& theError); |
127 | |
128 | //! Set the Error which will be transmitted to "calling routines". |
129 | Standard_EXPORT static void Error (const Handle(Standard_Failure)& aError); |
130 | |
c9246067 |
131 | //! Returns the current handler (closest in the stack in the current execution thread) |
42cf5bc1 |
132 | Standard_EXPORT static Standard_PErrorHandler FindHandler (const Standard_HandlerStatus theStatus, const Standard_Boolean theUnlink); |
133 | |
536a3cb8 |
134 | public: |
135 | //! Defines a base class for callback objects that can be registered |
136 | //! in the OCC error handler (the class simulating C++ exceptions) |
137 | //! so as to be correctly destroyed when error handler is activated. |
138 | //! |
139 | //! Note that this is needed only when Open CASCADE is compiled with |
9775fa61 |
140 | //! OCC_CONVERT_SIGNALS options (i.e. on UNIX/Linux). |
536a3cb8 |
141 | //! In that case, raising OCC exception and/or signal will not cause |
142 | //! C++ stack unwinding and destruction of objects created in the stack. |
143 | //! |
144 | //! This class is intended to protect critical objects and operations in |
145 | //! the try {} catch {} block from being bypassed by OCC signal or exception. |
146 | //! |
147 | //! Inherit your object from that class, implement DestroyCallback() function, |
148 | //! and call Register/Unregister in critical points. |
149 | //! |
150 | //! Note that you must ensure that your object has life span longer than |
151 | //! that of the try {} block in which it calls Register(). |
152 | class Callback |
153 | { |
154 | public: |
155 | DEFINE_STANDARD_ALLOC |
156 | |
157 | //! Registers this callback object in the current error handler (if found). |
59cfb82b |
158 | #if defined(OCC_CONVERT_SIGNALS) |
159 | Standard_EXPORT |
160 | #endif |
161 | void RegisterCallback(); |
536a3cb8 |
162 | |
163 | //! Unregisters this callback object from the error handler. |
59cfb82b |
164 | #if defined(OCC_CONVERT_SIGNALS) |
165 | Standard_EXPORT |
166 | #endif |
167 | void UnregisterCallback(); |
536a3cb8 |
168 | |
169 | //! Destructor |
59cfb82b |
170 | #if defined(OCC_CONVERT_SIGNALS) |
171 | Standard_EXPORT |
172 | #endif |
173 | virtual ~Callback(); |
536a3cb8 |
174 | |
175 | //! The callback function to perform necessary callback action. |
176 | //! Called by the exception handler when it is being destroyed but |
177 | //! still has this callback registered. |
178 | Standard_EXPORT virtual void DestroyCallback() = 0; |
179 | |
180 | protected: |
181 | |
182 | //! Empty constructor |
59cfb82b |
183 | #if defined(OCC_CONVERT_SIGNALS) |
184 | Standard_EXPORT |
185 | #endif |
186 | Callback(); |
536a3cb8 |
187 | |
188 | private: |
189 | Standard_Address myHandler; |
190 | Standard_Address myPrev; |
191 | Standard_Address myNext; |
192 | |
193 | friend class Standard_ErrorHandler; |
194 | }; |
195 | |
c9246067 |
196 | private: |
42cf5bc1 |
197 | |
198 | Standard_PErrorHandler myPrevious; |
199 | Handle(Standard_Failure) myCaughtError; |
200 | Standard_JmpBuf myLabel; |
201 | Standard_HandlerStatus myStatus; |
202 | Standard_ThreadId myThread; |
536a3cb8 |
203 | Callback* myCallbackPtr; |
42cf5bc1 |
204 | |
c9246067 |
205 | friend class Standard_Failure; |
42cf5bc1 |
206 | }; |
207 | |
9775fa61 |
208 | // If OCC_CONVERT_SIGNALS is not defined, |
536a3cb8 |
209 | // provide empty inline implementation |
9775fa61 |
210 | #if ! defined(OCC_CONVERT_SIGNALS) |
536a3cb8 |
211 | inline Standard_ErrorHandler::Callback::Callback () |
212 | : myHandler(0), myPrev(0), myNext(0) |
213 | { |
214 | } |
215 | inline Standard_ErrorHandler::Callback::~Callback () |
216 | { |
1bd04b5a |
217 | (void)myHandler; |
218 | (void)myPrev; |
536a3cb8 |
219 | } |
220 | inline void Standard_ErrorHandler::Callback::RegisterCallback () |
221 | { |
222 | } |
223 | inline void Standard_ErrorHandler::Callback::UnregisterCallback () |
224 | { |
225 | } |
226 | #endif |
227 | |
228 | // Definition of the old name "Standard_ErrorHandlerCallback" was kept for compatibility |
229 | typedef Standard_ErrorHandler::Callback Standard_ErrorHandlerCallback; |
230 | |
42cf5bc1 |
231 | #endif // _Standard_ErrorHandler_HeaderFile |