0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[occt.git] / src / Standard / Standard_ErrorHandler.hxx
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>
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>
27 #include <Standard_Type.hxx>
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 //!
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
48 #if defined(OCC_CONVERT_SIGNALS)
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
58   // Suppress GCC warning "variable ...  might be clobbered by 'longjmp' or 'vfork'"
59   #if defined(__GNUC__) && ! defined(__INTEL_COMPILER) && ! defined(__clang__)
60   #pragma GCC diagnostic ignored "-Wclobbered"
61   #endif
62
63 #else
64
65   // Normal Exceptions (for example WNT with MSVC and option /GHa)
66   #define OCC_CATCH_SIGNALS
67
68 #endif
69
70 class Standard_Failure;
71
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.
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();
93
94   //! Destructor
95   ~Standard_ErrorHandler()
96   {
97     Destroy();
98   }
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
108   Standard_JmpBuf& Label() { return myLabel; }
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
119 private:
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   
131   //! Returns the current handler (closest in the stack in the current execution thread)
132   Standard_EXPORT static Standard_PErrorHandler FindHandler (const Standard_HandlerStatus theStatus, const Standard_Boolean theUnlink);
133
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
140   //! OCC_CONVERT_SIGNALS options (i.e. on UNIX/Linux).
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).
158     void RegisterCallback();
159
160     //! Unregisters this callback object from the error handler.
161     void UnregisterCallback();
162
163     //! Destructor
164     virtual ~Callback();
165
166     //! The callback function to perform necessary callback action.
167     //! Called by the exception handler when it is being destroyed but
168     //! still has this callback registered.
169     Standard_EXPORT virtual void DestroyCallback() = 0;
170
171   protected:
172
173     //! Empty constructor
174     Callback();
175
176   private:
177     Standard_Address myHandler;
178     Standard_Address myPrev;
179     Standard_Address myNext;
180
181   friend class Standard_ErrorHandler;
182   };
183
184 private:
185
186   Standard_PErrorHandler myPrevious;
187   Handle(Standard_Failure) myCaughtError;
188   Standard_JmpBuf myLabel;
189   Standard_HandlerStatus myStatus;
190   Standard_ThreadId myThread;
191   Callback* myCallbackPtr;
192
193   friend class Standard_Failure;
194 };
195
196 // If OCC_CONVERT_SIGNALS is not defined,
197 // provide empty inline implementation
198 #if ! defined(OCC_CONVERT_SIGNALS)
199 inline Standard_ErrorHandler::Callback::Callback ()
200        : myHandler(0), myPrev(0), myNext(0)
201 {
202 }
203 inline Standard_ErrorHandler::Callback::~Callback ()
204 {
205   (void)myHandler;
206   (void)myPrev;
207 }
208 inline void Standard_ErrorHandler::Callback::RegisterCallback ()
209 {
210 }
211 inline void Standard_ErrorHandler::Callback::UnregisterCallback ()
212 {
213 }
214 #endif
215
216 // Definition of the old name "Standard_ErrorHandlerCallback" was kept for compatibility
217 typedef Standard_ErrorHandler::Callback Standard_ErrorHandlerCallback;
218
219 #endif // _Standard_ErrorHandler_HeaderFile