0028217: Error handling is not thread safe and causing memory corruption and sporadic...
[occt.git] / src / Standard / Standard_Failure.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Standard_ErrorHandler.hxx>
17 #include <Standard_Failure.hxx>
18 #include <Standard_Macro.hxx>
19 #include <Standard_NoSuchObject.hxx>
20 #include <Standard_PCharacter.hxx>
21 #include <Standard_Type.hxx>
22 #include <Standard_TypeMismatch.hxx>
23
24 #include <string.h>
25 IMPLEMENT_STANDARD_RTTIEXT(Standard_Failure,Standard_Transient)
26
27 static Standard_CString allocate_message(const Standard_CString AString)
28 {
29   Standard_CString aStr = 0;
30   if(AString) {
31     const Standard_Size aLen = strlen(AString);
32     aStr = (Standard_CString) malloc(aLen+sizeof(Standard_Integer)+1);
33     if (aStr) {
34       Standard_PCharacter pStr=(Standard_PCharacter)aStr;
35       strcpy(pStr+sizeof(Standard_Integer),AString);
36       *((Standard_Integer*)aStr) = 1;
37     }
38   }
39   return aStr;
40 }
41
42 static Standard_CString copy_message(Standard_CString aMessage)
43 {
44   Standard_CString aStr = 0;
45   if(aMessage) {
46     aStr = aMessage;
47     (*((Standard_Integer*)aStr))++;
48   }
49   return aStr;
50 }
51
52 static void deallocate_message(Standard_CString aMessage)
53 {
54   if(aMessage) {
55     (*((Standard_Integer*)aMessage))--;
56     if(*((Standard_Integer*)aMessage)==0)
57       free((void*)aMessage);
58   }
59 }
60
61 // Define Standard_THREADLOCAL modifier as C++11 thread_local keyword
62 // where it is available.
63 #if (defined(__INTEL_COMPILER) && __INTEL_COMPILER > 1400) || \
64     (defined(__clang__)) /* assume standard CLang > 3.3 or XCode >= 8 */ || \
65     (defined(_MSC_VER) && _MSC_VER >= 1800) /* MSVC++ >= 14 */ || \
66     (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) /* GCC >= 4.8 */
67   #define Standard_THREADLOCAL thread_local
68 #else
69   #define Standard_THREADLOCAL
70 #endif
71
72 // ******************************************************************
73 //                           Standard_Failure                       *
74 // ******************************************************************
75 #ifndef NO_CXX_EXCEPTION
76 static Standard_THREADLOCAL Handle(Standard_Failure) RaisedError;
77 #endif
78 // ------------------------------------------------------------------
79 //
80 // ------------------------------------------------------------------
81 Standard_Failure::Standard_Failure ()
82 : myMessage(NULL) 
83 {
84 }
85
86 // ------------------------------------------------------------------
87 // Create returns mutable Failure;
88 // ------------------------------------------------------------------
89 Standard_Failure::Standard_Failure (const Standard_CString AString) 
90 :  myMessage(NULL)
91 {
92   myMessage = allocate_message(AString);
93 }
94
95 Standard_Failure::Standard_Failure (const Standard_Failure& theFailure) 
96 : Standard_Transient(theFailure)
97 {
98   myMessage = copy_message(theFailure.myMessage);
99 }
100
101 Standard_Failure::~Standard_Failure()
102 {
103   deallocate_message(myMessage);
104 }
105
106 void Standard_Failure::SetMessageString(const Standard_CString AString)
107 {
108   if ( AString == GetMessageString() ) return;
109   deallocate_message(myMessage);
110   myMessage = allocate_message(AString);
111 }
112
113 // ------------------------------------------------------------------
114 // Caught (myclass) returns mutable Failure raises NoSuchObject ;
115 // ------------------------------------------------------------------
116 Handle(Standard_Failure) Standard_Failure::Caught() 
117 {
118 #ifdef NO_CXX_EXCEPTION
119   return Standard_ErrorHandler::LastCaughtError();
120 #else
121   return RaisedError ;
122 #endif
123 }
124
125 // ------------------------------------------------------------------
126 // Raise (myclass; aMessage: CString = "") ;
127 // ------------------------------------------------------------------
128 void Standard_Failure::Raise (const Standard_CString AString) 
129
130   Handle(Standard_Failure) E = new Standard_Failure()  ;
131   E->Reraise (AString) ;
132 }
133
134 // ------------------------------------------------------------------
135 // Raise(myclass; aReason: in out SStream) ;
136 // ------------------------------------------------------------------
137 void Standard_Failure::Raise (const Standard_SStream& AReason) 
138
139   Handle(Standard_Failure) E = new Standard_Failure();
140   E->Reraise (AReason);
141 }
142
143 // ------------------------------------------------------------------
144 // Reraise (me: mutable; aMessage: CString) ;
145 // ------------------------------------------------------------------
146 void Standard_Failure::Reraise (const Standard_CString AString) 
147 {
148   SetMessageString(AString);
149   Reraise();
150 }
151
152 void Standard_Failure::Reraise (const Standard_SStream& AReason) 
153 {
154   SetMessageString(AReason.str().c_str());
155   Reraise();
156 }
157
158 void Standard_Failure::Reraise () 
159 {
160 #ifdef NO_CXX_EXCEPTION
161   Standard_ErrorHandler::Error (this);
162   Standard_ErrorHandler::Abort (this);
163 #else
164   RaisedError = this;
165   Throw();
166 #endif
167 }
168
169 void Standard_Failure::Jump()
170 {
171 #if defined (NO_CXX_EXCEPTION) || defined (OCC_CONVERT_SIGNALS)
172   Standard_ErrorHandler::Error (this);
173   Standard_ErrorHandler::Abort (this);
174 #else
175   RaisedError = this;
176   Throw();
177 #endif
178 }
179
180
181 // ------------------------------------------------------------------
182 // Throw (me) is virtual ;
183 // ------------------------------------------------------------------
184 void Standard_Failure::Throw() const
185 {
186 #ifndef NO_CXX_EXCEPTION
187   throw *this;
188 #endif
189 }
190
191 // ------------------------------------------------------------------
192 // Print (me; s: in out OStream) returns OStream;
193 // ------------------------------------------------------------------
194 void Standard_Failure::Print (Standard_OStream& AStream) const
195 {
196 if(myMessage){ 
197     AStream << DynamicType() << ": " << GetMessageString(); 
198  } 
199  else { 
200     AStream << DynamicType();
201  }
202 }
203
204 Handle(Standard_Failure) Standard_Failure::NewInstance(const Standard_CString AString)
205 {
206   return new Standard_Failure(AString)  ;
207 }
208
209 //=======================================================================
210 //function : GetMessageString
211 //purpose  : Returns error message
212 //=======================================================================
213 Standard_CString Standard_Failure::GetMessageString () const
214 {
215   return (myMessage ? myMessage+sizeof(Standard_Integer) : "");
216 }
217