[omniORB] omniORB 3/4 create_POA deadlocks
Teemu Torma
tot@trema.com
Thu Oct 10 22:34:00 2002
--------------Boundary-00=_3WBSLNR6MZ2FVBCINEZ8
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
In omniORB 3.0 (and 4, since the code is the same), create_POA deadlocks=20
if we are creating a poa and another one of the same name is being=20
destroyed. create_POA tries to deal with this, but unfortunately the=20
locking conflicts between create_POA and do_destroy and will cause a=20
deadlock. Also create_POA does nothing to prevent the old poa of the=20
same name being deleted whilst still referencing to it.
Please see the diffs against omniORB 3.0 to fix the deadlock problem. =20
Whilst testing my changes, I noticed another problem in destroying=20
poa's. In destroy method, we check if pd_destroyed, throw an error,=20
else if pd_dying, wait for the poa to die. =20
Firstly, it does not seem reasonable to behave differently depending on=20
the current phase of the internal destruction, and secondly, this=20
causes problems if you destroy a poa under the root poa without waiting=20
for completion, and do orb shutdown.=20
In the latter case, root poa tries to delete the child poa which is=20
already being destroyed, and if the child destruction has hit the phase=20
when pd_destroyed =3D 1, an exception is thrown in a loop until the=20
destruction is complete (see do_destroy method).
Again, omniORB 4 looks identical to omniORB 3 regarding the destruction. =
=20
I did not do anything for that, since I have no idea what CORBA spec=20
says about the issue.
Teemu
--------------Boundary-00=_3WBSLNR6MZ2FVBCINEZ8
Content-Type: text/x-diff;
charset="us-ascii";
name="omniorb3-poa.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="omniorb3-poa.diff"
Index: src/lib/omniORB2/orbcore/poa.cc
===================================================================
RCS file: /trema/cvs/fk/tools/omniorb/src/lib/omniORB2/orbcore/Attic/poa.cc,v
retrieving revision 1.1.1.3
diff -c -u -r1.1.1.3 poa.cc
--- src/lib/omniORB2/orbcore/poa.cc 5 Jan 2001 13:38:49 -0000 1.1.1.3
+++ src/lib/omniORB2/orbcore/poa.cc 10 Oct 2002 21:12:47 -0000
@@ -415,47 +415,95 @@
transfer_and_check_policies(policy, policies);
- omni_tracedmutex_lock sync(poa_lock);
- omni_tracedmutex_lock sync2(pd_lock);
+ poa_lock.lock ();
+ pd_lock.lock ();
+ CORBA::Boolean locked = 1;
+
+ try {
+ // If an adapter of the given name exists, but is in the
+ // process of being destroyed, we should block until
+ // that has completed, and then allow the new one to be
+ // created. Ref CORBA 2.3 11.3.8.4
+
+ omniOrbPOA* p = find_child(adapter_name);
+ if( p ) {
+ // Lock it and keep one ref count for us.
+ p->pd_lock.lock ();
+ p->incrRefCount ();
+
+ if( p->pd_dying ) {
+
+ // Release other locks that we do not get deadlock
+ // during the possible destruction.
+ pd_lock.unlock ();
+ poa_lock.unlock ();
+ locked = 0;
+
+ if( omniORB::trace(10) ) {
+ omniORB::logger l;
+ l << "Waiting for destruction of POA(" << adapter_name << ").\n";
+ }
+
+ while( p->pd_destroyed != 2 ) p->pd_deathSignal.wait();
+
+ p->pd_lock.unlock();
+ p->decrRefCount();
+
+ if( omniORB::trace(10) ) {
+ omniORB::logger l;
+ l << "Continuing the creation of POA(" << adapter_name << ").\n";
+ }
+
+ pd_lock.lock();
+ poa_lock.lock();
+ locked = 1;
+
+ // Verify that it is gone.
+ OMNIORB_ASSERT(find_child(adapter_name) == 0);
+ }
+ else {
+ p->pd_lock.unlock();
+ p->decrRefCount();
+ throw AdapterAlreadyExists();
+ }
+ }
- CHECK_NOT_DYING();
+ CHECK_NOT_DYING();
- // If an adapter of the given name exists, but is in the
- // process of being destroyed, we should block until
- // that has completed, and then allow the new one to be
- // created. Ref CORBA 2.3 11.3.8.4
-
- omniOrbPOA* p = find_child(adapter_name);
- if( p ) {
- omni_tracedmutex_lock sync(p->pd_lock);
- if( p->pd_dying ) {
- while( p->pd_destroyed != 2 ) p->pd_deathSignal.wait();
- OMNIORB_ASSERT(find_child(adapter_name) == 0);
- }
+ if( CORBA::is_nil(manager) )
+ manager = new omniOrbPOAManager();
else
- throw AdapterAlreadyExists();
- }
+ PortableServer::POAManager::_duplicate(manager);
+
+ omniOrbPOA* poa = new omniOrbPOA(adapter_name,
+ (omniOrbPOAManager*) manager,
+ policy, this);
+
+ insert_child(poa);
+
+ pd_lock.unlock();
+ poa_lock.unlock();
+ locked = 0;
- if( CORBA::is_nil(manager) )
- manager = new omniOrbPOAManager();
- else
- PortableServer::POAManager::_duplicate(manager);
-
- omniOrbPOA* poa = new omniOrbPOA(adapter_name, (omniOrbPOAManager*) manager,
- policy, this);
-
- insert_child(poa);
-
- poa->adapterActive();
-
- // Need to ensure state is not changed from HOLDING if POA is
- // being created by an adapter activator. So in this case do
- // not attach the new poa to the manager.
- if( !is_adapteractivating_child(adapter_name) )
- ((omniOrbPOAManager*) manager)->gain_poa(poa);
+ poa->adapterActive();
- poa->incrRefCount();
- return poa;
+ // Need to ensure state is not changed from HOLDING if POA is
+ // being created by an adapter activator. So in this case do
+ // not attach the new poa to the manager.
+ if( !is_adapteractivating_child(adapter_name) )
+ ((omniOrbPOAManager*) manager)->gain_poa(poa);
+
+ poa->incrRefCount();
+
+ return poa;
+ }
+ catch (...) {
+ if( locked ) {
+ pd_lock.unlock();
+ poa_lock.unlock();
+ }
+ throw;
+ }
}
--------------Boundary-00=_3WBSLNR6MZ2FVBCINEZ8--