0031681: Foundation Classes - Shared Libraries Cannot Be Loaded
[occt.git] / src / Standard / Standard_ErrorHandler.cxx
old mode 100755 (executable)
new mode 100644 (file)
index ea8801e..7129919
@@ -1,20 +1,16 @@
 // Copyright (c) 1998-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 //============================================================================
 //==== Titre: Standard_ErrorHandler.cxx
 //============================================================================
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_Failure.hxx>
-#include <Standard_ErrorHandlerCallback.hxx>
 #include <Standard_Mutex.hxx>
 #include <Standard.hxx>
 
-#ifndef WNT
+#ifndef _WIN32
 #include <pthread.h>
 #else
 #include <windows.h>
 //==== The top of the Errors Stack ===========================================
 static Standard_ErrorHandler* Top = 0;
 
-// A mutex to protect from concurrent access to Top
-// Note that we should NOT use Sentry while in this class, as Sentry
-// would register mutex as callback in the current exception handler
-static Standard_Mutex theMutex; 
+//! A mutex to protect from concurrent access to Top.
+//! Mutex is defined as function to avoid issues caused by
+//! an undefined static variables initialization order across compilation units (@sa #0031681 bug).
+//! Note that we should NOT use Sentry while in this class, as Sentry
+//! would register mutex as callback in the current exception handler.
+static Standard_Mutex& GetMutex()
+{
+  static Standard_Mutex theMutex;
+  return theMutex;
+}
 
 static inline Standard_ThreadId GetThreadID()
 {
-#ifndef WNT
-  return pthread_self();
+#ifndef _WIN32
+  return (Standard_ThreadId)pthread_self();
 #else
   return GetCurrentThreadId();
 #endif
@@ -67,11 +68,12 @@ Standard_ErrorHandler::Standard_ErrorHandler () :
        myStatus(Standard_HandlerVoid), myCallbackPtr(0)
 {
   myThread   = GetThreadID();
+  memset (&myLabel, 0, sizeof(myLabel));
 
-  theMutex.Lock();
+  GetMutex().Lock();
   myPrevious = Top;
   Top        = this;
-  theMutex.Unlock();
+  GetMutex().Unlock();
 }
 
 
@@ -98,7 +100,7 @@ void Standard_ErrorHandler::Destroy()
 void Standard_ErrorHandler::Unlink()
 {
   // put a lock on the stack
-  theMutex.Lock();
+  GetMutex().Lock();
   
   Standard_ErrorHandler* aPrevious = 0;
   Standard_ErrorHandler* aCurrent = Top;
@@ -110,7 +112,7 @@ void Standard_ErrorHandler::Unlink()
   }
   
   if(aCurrent==0) {
-    theMutex.Unlock();
+    GetMutex().Unlock();
     return;
   }
   
@@ -122,13 +124,13 @@ void Standard_ErrorHandler::Unlink()
     aPrevious->myPrevious=aCurrent->myPrevious;
   }
   myPrevious = 0;
-  theMutex.Unlock();
+  GetMutex().Unlock();
 
   // unlink and destroy all registered callbacks
   Standard_Address aPtr = aCurrent->myCallbackPtr;
   myCallbackPtr = 0;
   while ( aPtr ) {
-    Standard_ErrorHandlerCallback* aCallback = (Standard_ErrorHandlerCallback*)aPtr;
+    Standard_ErrorHandler::Callback* aCallback = (Standard_ErrorHandler::Callback*)aPtr;
     aPtr = aCallback->myNext;
     // Call destructor explicitly, as we know that it will not be called automatically
     aCallback->DestroyCallback();
@@ -143,7 +145,7 @@ void Standard_ErrorHandler::Unlink()
 Standard_Boolean Standard_ErrorHandler::IsInTryBlock()
 {
   Standard_ErrorHandler* anActive = FindHandler(Standard_HandlerVoid, Standard_False);
-  return anActive != NULL && anActive->myLabel != NULL;
+  return anActive != NULL;
 }
 
 
@@ -157,10 +159,10 @@ void Standard_ErrorHandler::Abort (const Handle(Standard_Failure)& theError)
   Standard_ErrorHandler* anActive = FindHandler(Standard_HandlerVoid, Standard_True);
 
   //==== Check if can do the "longjmp" =======================================
-  if(anActive == NULL || anActive->myLabel == NULL) {
-    cerr << "*** Abort *** an exception was raised, but no catch was found." << endl;
+  if(anActive == NULL) {
+    std::cerr << "*** Abort *** an exception was raised, but no catch was found." << std::endl;
     if (!theError.IsNull())
-      cerr << "\t... The exception is:" << theError->GetMessageString() << endl;
+      std::cerr << "\t... The exception is:" << theError->GetMessageString() << std::endl;
     exit(1);
   }
 
@@ -221,7 +223,7 @@ Standard_ErrorHandler* Standard_ErrorHandler::FindHandler(const Standard_Handler
                                                           const Standard_Boolean theUnlink)
 {
   // lock the stack
-  theMutex.Lock();
+  GetMutex().Lock();
     
   // Find the current ErrorHandler Accordin tread
   Standard_ErrorHandler* aPrevious = 0;
@@ -266,7 +268,49 @@ Standard_ErrorHandler* Standard_ErrorHandler::FindHandler(const Standard_Handler
       aStop = Standard_True;
     }
   }
-  theMutex.Unlock();
+  GetMutex().Unlock();
   
   return anActive;
 }
+
+#if defined(OCC_CONVERT_SIGNALS)
+
+Standard_ErrorHandler::Callback::Callback ()
+  : myHandler(0), myPrev(0), myNext(0)
+{
+}
+
+Standard_ErrorHandler::Callback::~Callback ()
+{
+  UnregisterCallback();
+}
+
+void Standard_ErrorHandler::Callback::RegisterCallback ()
+{
+  if ( myHandler ) return; // already registered
+
+  // find current active exception handler
+  Standard_ErrorHandler *aHandler =
+    Standard_ErrorHandler::FindHandler(Standard_HandlerVoid, Standard_False);
+
+  // if found, add this callback object first to the list
+  if ( aHandler ) {
+    myHandler = aHandler;
+    myNext = aHandler->myCallbackPtr;
+    if ( myNext ) ((Standard_ErrorHandler::Callback*)myNext)->myPrev = this;
+    aHandler->myCallbackPtr = this;
+  }
+}
+
+void Standard_ErrorHandler::Callback::UnregisterCallback ()
+{
+  if ( ! myHandler ) return;
+  if ( myNext )
+    ((Standard_ErrorHandler::Callback*)myNext)->myPrev = myPrev;
+  if ( myPrev )
+    ((Standard_ErrorHandler::Callback*)myPrev)->myNext = myNext;
+  else if ( ((Standard_ErrorHandler*)myHandler)->myCallbackPtr == this)
+    ((Standard_ErrorHandler*)myHandler)->myCallbackPtr = (Standard_ErrorHandler::Callback*)myNext;
+  myHandler = myNext = myPrev = 0;
+}
+#endif