0028217: Error handling is not thread safe and causing memory corruption and sporadic...
[occt.git] / src / Standard / Standard_Failure.cxx
CommitLineData
b311480e 1// Copyright (c) 1998-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
7fd59977 14
42cf5bc1 15
7fd59977 16#include <Standard_ErrorHandler.hxx>
42cf5bc1 17#include <Standard_Failure.hxx>
7fd59977 18#include <Standard_Macro.hxx>
42cf5bc1 19#include <Standard_NoSuchObject.hxx>
7fd59977 20#include <Standard_PCharacter.hxx>
42cf5bc1 21#include <Standard_Type.hxx>
22#include <Standard_TypeMismatch.hxx>
7fd59977 23
42cf5bc1 24#include <string.h>
92efcf78 25IMPLEMENT_STANDARD_RTTIEXT(Standard_Failure,Standard_Transient)
26
7fd59977 27static Standard_CString allocate_message(const Standard_CString AString)
28{
29 Standard_CString aStr = 0;
30 if(AString) {
31 const Standard_Size aLen = strlen(AString);
a73267f2 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 }
7fd59977 38 }
39 return aStr;
7fd59977 40}
41
42static 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
52static void deallocate_message(Standard_CString aMessage)
53{
54 if(aMessage) {
55 (*((Standard_Integer*)aMessage))--;
56 if(*((Standard_Integer*)aMessage)==0)
a73267f2 57 free((void*)aMessage);
7fd59977 58 }
59}
60
b3d20c7f 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
7fd59977 71
72// ******************************************************************
73// Standard_Failure *
74// ******************************************************************
75#ifndef NO_CXX_EXCEPTION
b3d20c7f 76static Standard_THREADLOCAL Handle(Standard_Failure) RaisedError;
7fd59977 77#endif
78// ------------------------------------------------------------------
79//
80// ------------------------------------------------------------------
81Standard_Failure::Standard_Failure ()
82: myMessage(NULL)
83{
84}
85
86// ------------------------------------------------------------------
87// Create returns mutable Failure;
88// ------------------------------------------------------------------
89Standard_Failure::Standard_Failure (const Standard_CString AString)
90: myMessage(NULL)
91{
92 myMessage = allocate_message(AString);
93}
94
a9b30f0a 95Standard_Failure::Standard_Failure (const Standard_Failure& theFailure)
96: Standard_Transient(theFailure)
7fd59977 97{
a9b30f0a 98 myMessage = copy_message(theFailure.myMessage);
7fd59977 99}
100
4db4247a 101Standard_Failure::~Standard_Failure()
7fd59977 102{
103 deallocate_message(myMessage);
104}
105
106void 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// ------------------------------------------------------------------
116Handle(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// ------------------------------------------------------------------
128void 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// ------------------------------------------------------------------
137void 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// ------------------------------------------------------------------
146void Standard_Failure::Reraise (const Standard_CString AString)
147{
148 SetMessageString(AString);
149 Reraise();
150}
151
152void Standard_Failure::Reraise (const Standard_SStream& AReason)
153{
7fd59977 154 SetMessageString(AReason.str().c_str());
7fd59977 155 Reraise();
156}
157
158void Standard_Failure::Reraise ()
159{
160#ifdef NO_CXX_EXCEPTION
a01039b9 161 Standard_ErrorHandler::Error (this);
162 Standard_ErrorHandler::Abort (this);
7fd59977 163#else
164 RaisedError = this;
165 Throw();
166#endif
167}
168
69ff08ff 169void Standard_Failure::Jump()
7fd59977 170{
171#if defined (NO_CXX_EXCEPTION) || defined (OCC_CONVERT_SIGNALS)
a01039b9 172 Standard_ErrorHandler::Error (this);
173 Standard_ErrorHandler::Abort (this);
7fd59977 174#else
175 RaisedError = this;
176 Throw();
177#endif
178}
179
180
181// ------------------------------------------------------------------
182// Throw (me) is virtual ;
183// ------------------------------------------------------------------
184void 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// ------------------------------------------------------------------
194void Standard_Failure::Print (Standard_OStream& AStream) const
195{
196if(myMessage){
197 AStream << DynamicType() << ": " << GetMessageString();
198 }
199 else {
200 AStream << DynamicType();
201 }
202}
203
204Handle(Standard_Failure) Standard_Failure::NewInstance(const Standard_CString AString)
205{
206 return new Standard_Failure(AString) ;
207}
4db4247a 208
209//=======================================================================
210//function : GetMessageString
211//purpose : Returns error message
212//=======================================================================
213Standard_CString Standard_Failure::GetMessageString () const
214{
215 return (myMessage ? myMessage+sizeof(Standard_Integer) : "");
216}
217