115784d0529a5362bb544eb65161e7c08ef6ead2
[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 NO_CXX_EXCEPTION is defined, "try" and "catch" are defined as
36 //! macros that use jumps to implement exception handling. 
37 //! See Standard_Failure::Reraise() for exception throwing code.
38 //! Note that this option is obsolete and useless for modern platforms.
39 //! 
40 //! If macro OCC_CONVERT_SIGNALS is defined, this enables macro OCC_CATCH_SIGNALS
41 //! that can be used in the code (often inside try {} blocks) to convert C-style 
42 //! signals to standard C++ exceptions. This works only when OSD::SetSignal()
43 //! is called to set appropriate signal handler. In the case of signal (like 
44 //! access violation, division by zero, etc.) it will jump to the nearest 
45 //! OCC_CATCH_SIGNALS in the call stack, which will then throw a C++ exception.
46 //! This method is useful for Unix and Linux systems where C++ exceptions
47 //! cannot be thrown from C signal handler.
48 //! 
49 //! On Windows with MSVC compiler, exceptions can be thrown directly from 
50 //! signal handler, this OCC_CONVERT_SIGNALS is not needed. Note however that
51 //! this requires that compiler option /EHa is used.
52
53 #ifdef NO_CXX_EXCEPTION
54
55   // No CXX Exceeptions, only jumps in all the cases.
56   //
57   // Note: In the current version setjmp is used. The alternative solution is to
58   // use sigsetjmp that stores the signal mask (to be checked)
59   // In the original implementation sigsetjmp is tried to use for SUN and IRIX
60   // in the following way:
61   //    #ifdef SOLARIS
62   //      #define DoesNotAbort(aHandler) !sigsetjmp(aHandler.Label(),1)
63   //    #endif
64
65   #define try               Standard_ErrorHandler _Function; \
66                             if(!setjmp(_Function.Label()))
67   #define catch(Error)        else if(_Function.Catches(STANDARD_TYPE(Error)))
68   #define OCC_CATCH_SIGNALS 
69
70   // Suppress GCC warning "variable ...  might be clobbered by 'longjmp' or 'vfork'"
71   #if defined(__GNUC__) && ! defined(__INTEL_COMPILER) && ! defined(__clang__)
72   #pragma GCC diagnostic ignored "-Wclobbered"
73   #endif
74
75 #elif defined(OCC_CONVERT_SIGNALS)
76
77   // Exceptions are raied as usual, signal cause jumps in the nearest 
78   // OCC_CATCH_SIGNALS and then thrown as exceptions.
79   #define OCC_CATCH_SIGNALS   Standard_ErrorHandler _aHandler; \
80                               if(setjmp(_aHandler.Label())) { \
81                                 _aHandler.Catches(STANDARD_TYPE(Standard_Failure)); \
82                                 _aHandler.Error()->Reraise(); \
83                               }
84
85   // Suppress GCC warning "variable ...  might be clobbered by 'longjmp' or 'vfork'"
86   #if defined(__GNUC__) && ! defined(__INTEL_COMPILER) && ! defined(__clang__)
87   #pragma GCC diagnostic ignored "-Wclobbered"
88   #endif
89
90 #else
91
92   // Normal Exceptions (for example WNT with MSVC and option /GHa)
93   #define OCC_CATCH_SIGNALS
94
95 #endif
96
97 class Standard_Failure;
98 class Standard_ErrorHandlerCallback;
99
100 //! Class implementing mechanics of conversion of signals to exceptions.
101 //!
102 //! Each instance of it stores data for jump placement, thread id,
103 //! and callbacks to be called during jump (for proper resource release).
104 //!
105 //! The active handlers are stored in the global stack, which is used
106 //! to find appropriate handler when signal is raised.
107
108 class Standard_ErrorHandler 
109 {
110 public:
111
112   DEFINE_STANDARD_ALLOC
113
114   
115   //! Create a ErrorHandler (to be used with try{}catch(){}).
116   //! It uses the "setjmp" and "longjmp" routines.
117   Standard_EXPORT Standard_ErrorHandler();
118   
119   //! Unlinks and checks if there is a raised exception.
120   Standard_EXPORT void Destroy();
121
122   //! Destructor
123   ~Standard_ErrorHandler()
124   {
125     Destroy();
126   }
127   
128   //! Removes handler from the handlers list
129   Standard_EXPORT void Unlink();
130   
131   //! Returns "True" if the caught exception has the same type
132   //! or inherits from "aType"
133   Standard_EXPORT Standard_Boolean Catches (const Handle(Standard_Type)& aType);
134   
135   //! Returns label for jump
136   Standard_JmpBuf& Label() { return myLabel; }
137   
138   //! Returns the current Error.
139   Standard_EXPORT Handle(Standard_Failure) Error() const;
140   
141   //! Returns the caught exception.
142   Standard_EXPORT static Handle(Standard_Failure) LastCaughtError();
143   
144   //! Test if the code is currently running in a try block
145   Standard_EXPORT static Standard_Boolean IsInTryBlock();
146
147 private:
148   
149   //! A exception is raised but it is not yet caught.
150   //! So Abort the current function and transmit the exception
151   //! to "calling routines".
152   //! Warning: If no catch is prepared for this exception, it displays the
153   //! exception name and calls "exit(1)".
154   Standard_EXPORT static void Abort (const Handle(Standard_Failure)& theError);
155   
156   //! Set the Error which will be transmitted to "calling routines".
157   Standard_EXPORT static void Error (const Handle(Standard_Failure)& aError);
158   
159   //! Returns the current handler (closest in the stack in the current execution thread)
160   Standard_EXPORT static Standard_PErrorHandler FindHandler (const Standard_HandlerStatus theStatus, const Standard_Boolean theUnlink);
161
162 private:
163
164   Standard_PErrorHandler myPrevious;
165   Handle(Standard_Failure) myCaughtError;
166   Standard_JmpBuf myLabel;
167   Standard_HandlerStatus myStatus;
168   Standard_ThreadId myThread;
169   Standard_Address myCallbackPtr;
170
171   friend class Standard_Failure;
172   friend class Standard_ErrorHandlerCallback;
173 };
174
175 #endif // _Standard_ErrorHandler_HeaderFile