0031681: Foundation Classes - Shared Libraries Cannot Be Loaded
authormpv <mpv@opencascade.com>
Thu, 30 Jul 2020 16:30:21 +0000 (19:30 +0300)
committerbugmaster <bugmaster@opencascade.com>
Sat, 22 Aug 2020 09:13:08 +0000 (12:13 +0300)
Standard_ErrorHandler now accesses global mutex via proxy function
instead of a global variable to avoid initialization order issues.

src/Standard/Standard_ErrorHandler.cxx

index 49ac0de..7129919 100644 (file)
 //==== The top of the Errors Stack ===========================================
 static Standard_ErrorHandler* Top = 0;
 
 //==== 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()
 {
 
 static inline Standard_ThreadId GetThreadID()
 {
@@ -64,10 +70,10 @@ Standard_ErrorHandler::Standard_ErrorHandler () :
   myThread   = GetThreadID();
   memset (&myLabel, 0, sizeof(myLabel));
 
   myThread   = GetThreadID();
   memset (&myLabel, 0, sizeof(myLabel));
 
-  theMutex.Lock();
+  GetMutex().Lock();
   myPrevious = Top;
   Top        = this;
   myPrevious = Top;
   Top        = this;
-  theMutex.Unlock();
+  GetMutex().Unlock();
 }
 
 
 }
 
 
@@ -94,7 +100,7 @@ void Standard_ErrorHandler::Destroy()
 void Standard_ErrorHandler::Unlink()
 {
   // put a lock on the stack
 void Standard_ErrorHandler::Unlink()
 {
   // put a lock on the stack
-  theMutex.Lock();
+  GetMutex().Lock();
   
   Standard_ErrorHandler* aPrevious = 0;
   Standard_ErrorHandler* aCurrent = Top;
   
   Standard_ErrorHandler* aPrevious = 0;
   Standard_ErrorHandler* aCurrent = Top;
@@ -106,7 +112,7 @@ void Standard_ErrorHandler::Unlink()
   }
   
   if(aCurrent==0) {
   }
   
   if(aCurrent==0) {
-    theMutex.Unlock();
+    GetMutex().Unlock();
     return;
   }
   
     return;
   }
   
@@ -118,7 +124,7 @@ void Standard_ErrorHandler::Unlink()
     aPrevious->myPrevious=aCurrent->myPrevious;
   }
   myPrevious = 0;
     aPrevious->myPrevious=aCurrent->myPrevious;
   }
   myPrevious = 0;
-  theMutex.Unlock();
+  GetMutex().Unlock();
 
   // unlink and destroy all registered callbacks
   Standard_Address aPtr = aCurrent->myCallbackPtr;
 
   // unlink and destroy all registered callbacks
   Standard_Address aPtr = aCurrent->myCallbackPtr;
@@ -217,7 +223,7 @@ Standard_ErrorHandler* Standard_ErrorHandler::FindHandler(const Standard_Handler
                                                           const Standard_Boolean theUnlink)
 {
   // lock the stack
                                                           const Standard_Boolean theUnlink)
 {
   // lock the stack
-  theMutex.Lock();
+  GetMutex().Lock();
     
   // Find the current ErrorHandler Accordin tread
   Standard_ErrorHandler* aPrevious = 0;
     
   // Find the current ErrorHandler Accordin tread
   Standard_ErrorHandler* aPrevious = 0;
@@ -262,7 +268,7 @@ Standard_ErrorHandler* Standard_ErrorHandler::FindHandler(const Standard_Handler
       aStop = Standard_True;
     }
   }
       aStop = Standard_True;
     }
   }
-  theMutex.Unlock();
+  GetMutex().Unlock();
   
   return anActive;
 }
   
   return anActive;
 }
@@ -307,4 +313,4 @@ void Standard_ErrorHandler::Callback::UnregisterCallback ()
     ((Standard_ErrorHandler*)myHandler)->myCallbackPtr = (Standard_ErrorHandler::Callback*)myNext;
   myHandler = myNext = myPrev = 0;
 }
     ((Standard_ErrorHandler*)myHandler)->myCallbackPtr = (Standard_ErrorHandler::Callback*)myNext;
   myHandler = myNext = myPrev = 0;
 }
-#endif
\ No newline at end of file
+#endif