Issue 675: Section 3.3.8.16:deactivate_object() operation (orb_revision) Source: (, ) Nature: Uncategorized Severity: Summary: Summary: Section states that the deactivate_object() operation doesn"t wait for etherialize operation to complete before it returns. This is impossible to implement in single-threaded ORB Resolution: Revised Text: Actions taken: August 13, 1997: received issue February 25, 1999: moved to cxx_revision March 8, 1999: moved from cxx_revision to orb_revision October 30, 2000: resolved October 30, 2000: closed issue Discussion: moved from cxx_revision to orb_revision End of Annotations:===== Return-Path: Sender: jon@sems.com Date: Wed, 13 Aug 1997 12:53:10 -0700 From: Jonathan Biggar Organization: Seagate Software, Network & Storage Management Group To: port-rtf@omg.org, issues@omg.org Subject: Yet another portability spec issue [I suppose that technically this is past the deadline (8/11), but does anyone really care about that?] Section 3.3.8.16 states that the deactivate_object() operation does not wait for the etherialize peration to complete before it returns. This is impossible to implement in a single-threaded ORB,and significantly complicates the implementation of a multi-threaded ORB. Besides, it would be impossible to portably test for this behavior anyway, given the vagarities of thread scheduling behaviors. This should be changed to say whether deactivate_object() waits until the etherialize() operation completes is an implementation dependent matter. Jon Biggar jon@sems.com Return-Path: Date: Wed, 01 Jul 1998 18:25:34 -0400 From: Jonathan Biggar Organization: Floorboard Software To: port-rtf@omg.org Subject: Proposal for Issues 663 and 675 Problem: When using a POA without a Servant Manager, there is no safe time to destroy a servant after calling deactivate_object() because the POA does not guarantee that there are no concurrent operations still in process on the object. Here is an example of attempting to implement the LifeCycle service remove operation() in C++: // IDL interface A : CosLifeCycle::LifeCycleObject { }; // C++ PortableServer::Current_var current; // set somewhere class MyA : public POA_A { public: void remove() throw(CORBA::SystemException, CosLifeCycle::NotRemovable) { PortableServer::POA_var poa = current->get_poa(); PortableServer::ObjectId_var oid = poa->servant_to_id(); poa->deactivate_object(oid); delete this; } }; This won't work, because when the servant is deleted, there is no guarantee that another concurrent operation isn't still using the object. So the thread that calls remove() can end up deleting the servant out from under another thread, causing memory corruption and a probable core dump. Proposal: Add the following text to the description of POA::deactivate_object() in section 9.3.8: If the POA does not have the USE_SERVANT_MANAGER policy, the call to deactivate_object() will not return until all current invocations on the object have completed, except for any invocations that are running in the context of the thread that called deactivate_object(). This provides the application a safe point where it can destroy the servant after it is deactivated while avoiding a deadlock. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: "George Scott" Date: Wed, 01 Jul 1998 20:22:34 -0700 From: "George M. Scott" Organization: Inprise Corporation To: port-rtf@omg.org Subject: Counter proposal for Issue 663 and 675 One of the goals Inprise has as part of our participation in this RTF is to eliminate as many of the current deadlock situations in the POA as possible. The current proposal on the table for issues 663 and 675 would introduce blocking behavior to POA::deactivate_object which has the potential to cause deadlock. For example, imagine a case where object A calls object B which calls deactivate_object() on A. Now object B simultaneously calls object A which also calls deactivate_object() on B. This will deadlock under the recently proposed revision (see Jonathan Biggar's email). When you include multiple remote objects into the mix the chances of deadlock only increase, and it is not even necessary to have co-recursive calls to deactivate_object for this to occur. For example consider object A on one machine and object B on a remote machine. A calls B which then calls a method on A which attempts to call deactivate_object on A. Under the current proposed revision this will always deadlock. These are not corner cases, and should clearly be supported without deadlocking. We feel the only change required to deactivate_object is to state what the behavior of POA calls will be for requests that are currently executing in an object which has been deactivated. For example, if there are two requests executing in the same object and the first request calls deactivate_object, and afterwards the second request calls servant_to_reference() what should happen? Should it throw ServantNotActive or return succesfully. It seems that it should complete successfully. Another situation to consider is what happens when either implicit or explicit (via activate_object) activation occurs after deactivate_object is called on an oid. Is that oid immediately available? Or must all the current requests complete processing before an object with the same oid be activated? We will open this up as a new issue and provide a proposal. The issues raised in 663 and 675 are really getting at problems with the C++ language mapping and not the behavior of deactivate_object. We don't believe we should be changing the behavior of the POA to address language mapping specific behavior such as memory management. Therefore, we propose the following resolutions to 663 and 675. --------------------------------------------------------------- Issue 663: Implementation problem with policy objects using root POA Nature: Revision Resolution: Transfer to C++ RTF (unless Dan thinks the port-rtf still has jurisdiction, I'm personally confused about who owns what in this case, I know the java-rtf own the Java POA mapping, not sure about C++) (We will be proposing a solution to this problem in that context) ---------------------------------------------------------------- Issue 675: deactivate_object() operation Nature: Revision Summary: deactivate_object() cannot be implemented in a single threaded environment because etherealization is delayed. Resolution: Closed with no action. This is an implementation detail which we and others have managed to work around in our single-threaded ORBs. The simplest way, for example, is to have a queue of objects to be etherealized, which the ORB can process as part of its event loop. George Return-Path: Date: Thu, 02 Jul 1998 11:57:55 -0400 From: Jonathan Biggar Organization: Floorboard Software To: "George M. Scott" CC: port-rtf@omg.org Subject: Re: Counter proposal for Issue 663 and 675 References: <359AFCFA.5C211F3E@inprise.com> Ok, I'll be big about it and admit you have found a serious problem with my proposal! :-) It looks like some kind of refcount is going to be necessary for the C++ mapping. I will respond to your proposal (in another message) with my comments. One question about issue 675. I have always wondered why the spec required that deactivate_object() return before the etherealize() call is made. Isn't this specifying implementation detail that is better left to the ORB implementor? Is there a deadlock or race condition that I haven't thought of that makes it a bad idea to just dispatch the etherealize() call directly from deactivate_object()? [Never mind, I just thought of the reason. I've left the question in this message for expository purposes.] The reason is that since concurrent operations may be still running on the object, you can't call etherealize right away until those operations complete, so you can end up with the same deadlock problems again if another thread calls deactivate_object() on the same object. Jon George M. Scott wrote: > One of the goals Inprise has as part of our participation in > this RTF is to eliminate as many of the current deadlock > situations in the POA as possible. The current proposal on the > table for issues 663 and 675 would introduce blocking behavior to > POA::deactivate_object which has the potential to cause deadlock. > > For example, imagine a case where object A calls object B which > calls deactivate_object() on A. Now object B simultaneously > calls object A which also calls deactivate_object() on B. This > will deadlock under the recently proposed revision (see Jonathan > Biggar's email). When you include multiple remote objects into > the mix the chances of deadlock only increase, and it is not even > necessary to have co-recursive calls to deactivate_object for > this to occur. For example consider object A on one machine > and object B on a remote machine. A calls B which then calls > a method on A which attempts to call deactivate_object on A. > Under the current proposed revision this will always deadlock. > These are not corner cases, and should clearly be supported > without deadlocking. > > We feel the only change required to deactivate_object is to > state what the behavior of POA calls will be for requests that > are currently executing in an object which has been deactivated. > For example, if there are two requests executing in the same > object and the first request calls deactivate_object, and > afterwards the second request calls servant_to_reference() what > should happen? Should it throw ServantNotActive or return > succesfully. It seems that it should complete successfully. > Another situation to consider is what happens when either > implicit or explicit (via activate_object) activation occurs > after deactivate_object is called on an oid. Is that oid > immediately available? Or must all the current requests complete > processing before an object with the same oid be activated? > We will open this up as a new issue and provide a proposal. > > The issues raised in 663 and 675 are really getting at problems > with the C++ language mapping and not the behavior of > deactivate_object. We don't believe we should be changing the > behavior of the POA to address language mapping specific behavior > such as memory management. > > Therefore, we propose the following resolutions to 663 and 675. > > --------------------------------------------------------------- > Issue 663: Implementation problem with policy objects using root POA > Nature: Revision > Resolution: Transfer to C++ RTF (unless Dan thinks the port-rtf > still has jurisdiction, I'm personally confused about who > owns what in this case, I know the java-rtf own the Java > POA mapping, not sure about C++) > > (We will be proposing a solution to this problem in that context) > > ---------------------------------------------------------------- > Issue 675: deactivate_object() operation > Nature: Revision > Summary: deactivate_object() cannot be implemented in a single > threaded environment because etherealization is delayed. > Resolution: Closed with no action. This is an implementation > detail which we and others have managed to work > around in our single-threaded ORBs. The simplest way, > for example, is to have a queue of objects to be > etherealized, which the ORB can process as part of > its event loop. > > George -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org