omniORB 4.0.1 destroy race condition

Teemu Torma <[email protected]> Thu, 8 May 2003 21:51:56 +0200
Newsgroups gmane.comp.corba.omniorb.devel
Message-ID <[email protected]>
To whom it may concern.

Whilst testing forthcoming valgrind 1.9.6 snapshot with omniORB 
application, it started reporting of mutex being unlocked by another 
thread than locker, or destroying a mutex still in use.

By reviewing poa.cc it seems that this problem can happen in two 
different places where we are doing

     while( pd_destroyed != 2 )  pd_deathSignal.wait();

but not holding a reference to the poa.  Thus when pd_deathSignal.wait() 
returns, in re-aquires the pd_lock, but at that point the poa might be 
being destructed or already completely deleted depending on the 
scheduling issues.

By making the necessary changes to have a reference count to the poa in 
these two places, the problem went away, and valgrind has been happy 
ever since.  Please see the attached patch.

Teemu

_______________________________________________
omniORB-dev mailing list
[email protected]
http://www.omniorb-support.com/mailman/listinfo/omniorb-dev
poa.diff (text/x-diff, 1.6 KB)
Index: src/lib/omniORB/orbcore/poa.cc
===================================================================
RCS file: /trema/cvs/fk/tools/omniorb/src/lib/omniORB/orbcore/poa.cc,v
retrieving revision 1.4
diff -c -u -r1.4 poa.cc
--- src/lib/omniORB/orbcore/poa.cc	26 Mar 2003 23:15:42 -0000	1.4
+++ src/lib/omniORB/orbcore/poa.cc	8 May 2003 19:43:16 -0000
@@ -698,22 +698,37 @@
   // invocations) and then remove self from parent.
 
   {
-    omni_tracedmutex_lock sync(pd_lock);
+    pd_lock.lock();
 
-    if( pd_destroyed )  OMNIORB_THROW(OBJECT_NOT_EXIST,
-				      OBJECT_NOT_EXIST_POANotInitialised,
-				      CORBA::COMPLETED_NO);
+    if( pd_destroyed ) {
+      pd_lock.unlock ();
+      OMNIORB_THROW(OBJECT_NOT_EXIST,
+		    OBJECT_NOT_EXIST_POANotInitialised,
+		    CORBA::COMPLETED_NO);
+    }
 
     if( pd_dying ) {
       // Need to be able to handle multiple concurrent calls to
       // destroy.  If destruction is in progress and wait_f_c is
       // true, must wait to complete.  Otherwise can just return.
-      if( wait_for_completion )
+      if( wait_for_completion ) {
+
+	incrRefCount();
+
 	while( pd_destroyed != 2 )  pd_deathSignal.wait();
+
+	pd_lock.unlock ();
+	decrRefCount();
+
+      } else {
+	pd_lock.unlock ();
+      }
       return;
     }
 
     pd_dying = 1;
+
+    pd_lock.unlock ();
   }
 
   {
@@ -2193,8 +2208,10 @@
   if( pd_dying ) {
     // If being destroyed by another thread, then we just
     // have to wait until that completes.
+    incrRefCount();
     while( pd_destroyed != 2 )  pd_deathSignal.wait();
     pd_lock.unlock();
+    decrRefCount();
     return;
   }