Issue 1627: Problems with deactivate_object() (cxx_revision) Source: (, ) Nature: Revision Severity: Summary: Summary: The POA does not properly define the behavior of POA operations for requests that are currently executing in an object that has been deactivated. Resolution: Close no change. This issue is already addressed in the CORBA 2.3 specification. Revised Text: Actions taken: July 2, 1998: received issue February 25, 1999: moved to cxx_revision June 13, 2000: closed issue Discussion: End of Annotations:===== Return-Path: Sender: "George Scott" Date: Wed, 01 Jul 1998 21:31:19 -0700 From: "George M. Scott" Organization: Inprise Corporation To: port-rtf@omg.org CC: issues@omg.org Subject: Problems with deactivate_object() The POA does not properly define the behavior of POA operations for requests that are currently executing in an object that 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? Our proposal is that once deactivate_object has been called on an object, that the object will remain in the active object map until all requests have completed execution. This means that all calls to servant_to_reference, etc. will continue to work and that calls to activate_object or implicit activation will fail with the appropriate exception. When all requests have completed, etherealization will occur. Calling deactivate_object() multiple times for an object which has already been deactivated has no effect. Newly arrived requests that arrive for the deactivated object will behave as if the POA were in the holding state. When the object is etherealized, any queued request will be treated as if they had just arrived and will behave accordingly (i.e., if a ServantActivator is present, it will result in incarnate being called.) Below is our proposed resolution to this issue: --------------------------------------------------------------- Issue XXXX: Problems with deactivate_object() Nature: Revision Summary: deactivate_object behavior is not defined when multiple concurrent active requests are executing in an object when it is deactivated. Resolution: Accepted for Corba RTF 2.3 Revision: Replace the second paragraph describing deactivate_object on page 9-35, section 9.3.8 with the following: This operation causes the ObjectId specified in the oid parameter to be . An ObjectId which has been deactivated cannot receive new requests until the ObjectId has been removed from the Active Object Map. Any new requests which arrive for a deactivated ObjectId will behave as if the POA for that ObjectId is in the holding state. A deactivated ObjectId is removed from the Active Object Map when all requests executing for that ObjectId have completed. If a servant manager is associated with the POA, ServantActivator::etherealize will be invoked with the oid and the associated servant after the ObjectId has been removed from the Active Object Map. Once an ObjectId has been removed from the Active Object Map and etherealized ( if necessary) it may then be reactivated through the usual mechanisms. Requests that arrived after deactivation and were queued will behave as if they were newly arrived after etherealization completes. The operation does not wait for requests or etherealization to complete and always returns immediately after deactivating the ObjectId. -------------------------------------------------------------- George Return-Path: Date: Mon, 06 Jul 1998 14:53:17 -0400 From: Paul H Kyzivat Organization: NobleNet To: "George M. Scott" CC: port-rtf@omg.org, issues@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> George M. Scott wrote: > > The POA does not properly define the behavior of POA operations > for requests that are currently executing in an object that > 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? > > Our proposal is that once deactivate_object has been called > on an object, that the object will remain in the active object > map until all requests have completed execution. This means > that all calls to servant_to_reference, etc. will continue > to work and that calls to activate_object or implicit activation > will fail with the appropriate exception. When all requests > have completed, etherealization will occur. Calling > deactivate_object() multiple times for an object which has already > been deactivated has no effect. > > Newly arrived requests that arrive for the deactivated object > will behave as if the POA were in the holding state. When > the object is etherealized, any queued request will be treated > as if they had just arrived and will behave accordingly (i.e., > if a ServantActivator is present, it will result in incarnate > being called.) > > Below is our proposed resolution to this issue: > > --------------------------------------------------------------- > Issue XXXX: Problems with deactivate_object() > Nature: Revision > > Summary: deactivate_object behavior is not defined when multiple > concurrent active requests are executing in an object > when it is deactivated. > > Resolution: Accepted for Corba RTF 2.3 > > Revision: Replace the second paragraph describing deactivate_object > on page 9-35, section 9.3.8 with the following: > > This operation causes the ObjectId specified in the oid > parameter to be . An ObjectId which has been > deactivated cannot receive new requests until the ObjectId > has been removed from the Active Object Map. Any new requests > which arrive for a deactivated ObjectId will behave as if the > POA for that ObjectId is in the holding state. A deactivated > ObjectId is removed from the Active Object Map when all requests > executing for that ObjectId have completed. If a servant manager > is associated with the POA, ServantActivator::etherealize will be > invoked with the oid and the associated servant after the ObjectId > has been removed from the Active Object Map. Once an ObjectId > has been removed from the Active Object Map and etherealized ( > if necessary) it may then be reactivated through the usual > mechanisms. Requests that arrived after deactivation and were > queued > will behave as if they were newly arrived after > etherealization completes. > > The operation does not wait for requests or etherealization to > complete and always returns immediately after deactivating the > ObjectId. This seems to single out objects that are the targets of invocations for special treatment. However the same sorts of problems can occur for objects that are not the targets of invocations. The proposal would result in different behavior in one case than the other. Attempting to make the change uniformly would be inordinately complex, and (in my opinion) would be no easier to use or clearer than the current situation. To clarify: when multiple requests are operating in parallel, one might deactivate an object that another may be using. If so, a subsequent POA operation (like id_to_servant) may return an unexpected error. Whether the object is the target of one of the requests is largely irrelevant. To "fix" this in general it will be necessary, during deactivation, to associate the ActiveObjectMap entry with all the requests in operation at that time. (This is a lot harder than just counting the number of requests outstanding for a particular servant.) The table entry must then be held until all those requests finish. Not only does this seem absurdly complex and expensive, but is harder to explain and use. When I deactivate something, I expect that it will no longer be active. I realize the proposal doesn't ask for so much. But doing less leads to very inconsistent behavior. Assume the situation I started with: a request in one thread deactivates an object while another request uses the same object. (In both cases the object is just data for the request, not its target.) With your proposal, these threads would see the object deactivation complete immediately. But if some other thread happened to be executing a request on the same object then they would see different behavior. I don't see any reason to do anything special for these cases, except what is already called regarding how _this() works in conjunction with the current invocation context. Return-Path: Sender: jon@floorboard.com Date: Wed, 08 Jul 1998 08:18:21 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org, issues@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> Paul H Kyzivat wrote: > This seems to single out objects that are the targets of invocations for > special treatment. However the same sorts of problems can occur for > objects that are not the targets of invocations. The proposal would > result in different behavior in one case than the other. Attempting to > make the change uniformly would be inordinately complex, and (in my > opinion) would be no easier to use or clearer than the current > situation. > > To clarify: when multiple requests are operating in parallel, one might > deactivate an object that another may be using. If so, a subsequent POA > operation (like id_to_servant) may return an unexpected error. Whether > the object is the target of one of the requests is largely irrelevant. This is much less dangerous a problem than the one identified, which is that in the C++ mapping, there is no safe place to destroy a servant since there is no way to guarantee that the servant isn't being used by someone else. This also avoids the problem with a continual request stream blocking the object deactivation forever. > To "fix" this in general it will be necessary, during deactivation, to > associate the ActiveObjectMap entry with all the requests in operation > at that time. (This is a lot harder than just counting the number of > requests outstanding for a particular servant.) The table entry must > then be held until all those requests finish. > > Not only does this seem absurdly complex and expensive, but is harder to > explain and use. When I deactivate something, I expect that it will no > longer be active. > > I realize the proposal doesn't ask for so much. But doing less leads to > very inconsistent behavior. Assume the situation I started with: a > request in one thread deactivates an object while another request uses > the same object. (In both cases the object is just data for the request, > not its target.) With your proposal, these threads would see the object > deactivation complete immediately. But if some other thread happened to > be executing a request on the same object then they would see different > behavior. > > I don't see any reason to do anything special for these cases, except > what is already called regarding how _this() works in conjunction with > the current invocation context. It seems to me that active invocations are treated specially throughout the POA spec. Why shouldn't we make the attempt to ensure that once an invocation is started, that it is allowed to complete unmolested? -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Wed, 08 Jul 1998 12:25:19 -0400 From: Paul H Kyzivat Organization: NobleNet To: Jonathan Biggar CC: "George M. Scott" , port-rtf@omg.org, issues@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> Jonathan Biggar wrote: > > This is much less dangerous a problem than the one identified, which > is > that in the C++ mapping, there is no safe place to destroy a servant > since there is no way to guarantee that the servant isn't being used > by > someone else. This also avoids the problem with a continual request > stream blocking the object deactivation forever. The problem addressed by the proposal doesn't appear to me to be the same problem as when to safely destroy a servant. Deactivation and servant destruction are separate - especially when a ServantActivator is involved. By using a ServantActivator, the etherealize method knows that there are no outstanding operations, so that from that perspective it is safe to delete the servant. This proposal seems to address something else - whether POA operations that look up by servant or that return a servant will continue to work for a time, for some callers, after deactivation is requested. I agree that there is still a problem of knowing when a servant can safely be destroyed, but I don't agree that this proposal is a necessary or sufficient part of the solution to that problem. There are also problems in the reference counting proposal, but that seems much closer to being a solution. > It seems to me that active invocations are treated specially > throughout > the POA spec. Why shouldn't we make the attempt to ensure that once > an > invocation is started, that it is allowed to complete unmolested? I guess we differ in what we consider molestation. Having the servant removed from the active object map during the execution of an operation is not necessarily incorrect. Consider a RETAIN & ACTIVE_OBJECT_MAP_ONLY poa. An operation on an object activated in this POA may decide to deactivate itself. It can call deactivate_object, and then may decide to delete itself. (This is legal C++!). With the proposed change, it would appear that another operation that happens to be in progress at the same time will be able to call id_to_servant after the deactivation and still be handed the servant that is about to destroy itself. This makes the problem of knowing when a servant is valid worse rather than better. Return-Path: Sender: jon@floorboard.com Date: Wed, 08 Jul 1998 09:48:22 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org, issues@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> <35A39D6F.879ACFE4@noblenet.com> Paul H Kyzivat wrote: > > Jonathan Biggar wrote: > > > > This is much less dangerous a problem than the one identified, > which > > is > > that in the C++ mapping, there is no safe place to destroy a > servant > > since there is no way to guarantee that the servant isn't being > used > > by > > someone else. This also avoids the problem with a continual > request > > stream blocking the object deactivation forever. > > The problem addressed by the proposal doesn't appear to me to be the > same problem as when to safely destroy a servant. Deactivation and > servant destruction are separate - especially when a > ServantActivator is > involved. By using a ServantActivator, the etherealize method knows > that > there are no outstanding operations, so that from that perspective > it is > safe to delete the servant. > > This proposal seems to address something else - whether POA > operations > that look up by servant or that return a servant will continue to > work > for a time, for some callers, after deactivation is requested. > > I agree that there is still a problem of knowing when a servant can > safely be destroyed, but I don't agree that this proposal is a > necessary > or sufficient part of the solution to that problem. There are also > problems in the reference counting proposal, but that seems much > closer > to being a solution. I see this as a general robustness issue. If I have to write all of my operation implementations with the idea that anyone can deactivate the object at anytime while I am in progress, I have to write a whole lot more code to handle this case. It's much easier for the ORB to make sure of this than for my application code to do so. > > It seems to me that active invocations are treated specially > > throughout > > the POA spec. Why shouldn't we make the attempt to ensure that > once > > an > > invocation is started, that it is allowed to complete unmolested? > > I guess we differ in what we consider molestation. Having the > servant > removed from the active object map during the execution of an > operation > is not necessarily incorrect. > > Consider a RETAIN & ACTIVE_OBJECT_MAP_ONLY poa. An operation on an > object activated in this POA may decide to deactivate itself. It can > call deactivate_object, and then may decide to delete itself. (This > is > legal C++!). Sure it's legal C++, but the current spec is entirely broken. Any operation implementation that calls deactivate_object() followed by deleting this, as the POA is currently specified is simply a core dump waiting to happen in a multithreaded environment. We must fix this, as quickly as possible, or we might as well consider the POA specification a failure. > With the proposed change, it would appear that another operation that > happens to be in progress at the same time will be able to call > id_to_servant after the deactivation and still be handed the servant > that is about to destroy itself. This makes the problem of knowing when > a servant is valid worse rather than better. This change is part of the package. In itself, it doesn't fix the problem with servant destruction, but paired with the appropriate language mapping solution (reference counts) it plugs the hole. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: "George Scott" Date: Mon, 13 Jul 1998 20:01:38 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Paul H Kyzivat CC: port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> Paul H Kyzivat wrote: > > George M. Scott wrote: > > > > > > --------------------------------------------------------------- > > Issue XXXX: Problems with deactivate_object() > > Nature: Revision > > > > Summary: deactivate_object behavior is not defined when multiple > > concurrent active requests are executing in an object > > when it is deactivated. > > > > Resolution: Accepted for Corba RTF 2.3 > > > > Revision: Replace the second paragraph describing > deactivate_object > > on page 9-35, section 9.3.8 with the following: > > > > This operation causes the ObjectId specified in the oid > > parameter to be . An ObjectId which has been > > deactivated cannot receive new requests until the ObjectId > > has been removed from the Active Object Map. Any new requests > > which arrive for a deactivated ObjectId will behave as if the > > POA for that ObjectId is in the holding state. A deactivated > > ObjectId is removed from the Active Object Map when all requests > > executing for that ObjectId have completed. If a servant manager > > is associated with the POA, ServantActivator::etherealize will be > > invoked with the oid and the associated servant after the ObjectId > > has been removed from the Active Object Map. Once an ObjectId > > has been removed from the Active Object Map and etherealized ( > > if necessary) it may then be reactivated through the usual > > mechanisms. Requests that arrived after deactivation and were > queued > > will behave as if they were newly arrived after > > etherealization completes. > > > > The operation does not wait for requests or etherealization to > > complete and always returns immediately after deactivating the > > ObjectId. > > This seems to single out objects that are the targets of invocations > for > special treatment. However the same sorts of problems can occur for > objects that are not the targets of invocations. The proposal would > result in different behavior in one case than the other. Attempting > to > make the change uniformly would be inordinately complex, and (in my > opinion) would be no easier to use or clearer than the current > situation. > > To clarify: when multiple requests are operating in parallel, one > might > deactivate an object that another may be using. If so, a subsequent > POA > operation (like id_to_servant) may return an unexpected > error. Whether > the object is the target of one of the requests is largely > irrelevant. Paul I have to disagree with you on this. If an object is processing multiple requests and it is deactivated it is essential that the requests that are currently executing can continue normal execution until completion of the request. Doing otherwise only lead to unpredictable and non- portable behavior in user code, and requires users to implement their own mechanisms to keep track of when it is safe to actually deactivate an object. This makes the implementation of COS LifeCycle and other services fairly complex, when they do not need to be. The POA is supposed to make user code more portable and easier to use, not the other way around. > To "fix" this in general it will be necessary, during deactivation, to > associate the ActiveObjectMap entry with all the requests in operation > at that time. (This is a lot harder than just counting the number of > requests outstanding for a particular servant.) The table entry must > then be held until all those requests finish. > > Not only does this seem absurdly complex and expensive, but is harder to > explain and use. When I deactivate something, I expect that it will no > longer be active. It is neither absurdly complex nor expensive. It simply requires keeping track of the number of active requests per object. Upon deactivate the object is flagged so no new requests can be processed, and when the request count hits zero it is etherealized if necessary. > I realize the proposal doesn't ask for so much. But doing less leads to > very inconsistent behavior. Assume the situation I started with: a > request in one thread deactivates an object while another request uses > the same object. (In both cases the object is just data for the request, > not its target.) With your proposal, these threads would see the object > deactivation complete immediately. But if some other thread happened to > be executing a request on the same object then they would see different > behavior. I'm a little confused by your example. If you are saying that threads would see different behavior based on the number of active requests, then I would say yes of course they do. If an object is deactivated and there are no active requests then its destruction is immediately apparent (though it may not yet be etherealized). If an object is deactivated and there are requests processing in that object, then the object's deactivation will not be apparent until all the requests executing in that object have completed. So the behavior will be different depending on the situation, but I think this is how it should be as these are two very different situations. > I don't see any reason to do anything special for these cases, except > what is already called regarding how _this() works in conjunction with > the current invocation context. I don't see why _this() should work for deactivated objects, but calls on the POA itself will not. This to me seems just as inconsistent as the problems you are complaining about in the proposal. George Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Tue, 14 Jul 1998 14:14:05 +1000 (EST) From: Michi Henning To: "George M. Scott" cc: Paul H Kyzivat , port-rtf@omg.org Subject: Re: Problems with deactivate_object() On Mon, 13 Jul 1998, George M. Scott wrote: > Paul I have to disagree with you on this. If an object is processing > multiple requests and it is deactivated it is essential that the requests > that are currently executing can continue normal execution until completion > of the request. Doing otherwise only lead to unpredictable and non- > portable behavior in user code, and requires users to implement their > own mechanisms to keep track of when it is safe to actually deactivate > an object. This makes the implementation of COS LifeCycle and other > services fairly complex, when they do not need to be. The POA is supposed > to make user code more portable and easier to use, not the other way > around. I couldn't agree more. Ever tried to implement LifeCycle::remove on an ORB that doesn't allow you detect when all requests have left the servant? Damn near impossible... > It is neither absurdly complex nor expensive. It simply requires keeping > track of the number of active requests per object. Upon deactivate the > object is flagged so no new requests can be processed, and when the request > count hits zero it is etherealized if necessary. That seems to be the obvious implementation. I don't see any excessive complexity there either. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: Date: Tue, 14 Jul 1998 09:28:31 -0400 From: Paul H Kyzivat Organization: NobleNet To: "George M. Scott" CC: port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> George M. Scott wrote: > > Paul I have to disagree with you on this. If an object is > processing > multiple requests and it is deactivated it is essential that the > requests > that are currently executing can continue normal execution until > completion > of the request. Doing otherwise only lead to unpredictable and non- > portable behavior in user code, and requires users to implement > their > own mechanisms to keep track of when it is safe to actually > deactivate > an object. This makes the implementation of COS LifeCycle and other > services fairly complex, when they do not need to be. The POA is > supposed > to make user code more portable and easier to use, not the other way > around. My point is that deactivating an object that is servicing an invocation is no worse (and no better) than deactivating an object that is being used as an operand by an invocation. Once the request has been dispatched there is no longer any logical necessity for the object to be activated for the request to go to completion. Of course it would be bad for the servant to be deleted out from under the method without its knowledge, but that is a separate issue. The rules for etherealization already prevent the etherealization from taking place until the invocation completes. So, when a ServantActivator is present all we are talking about is whether the mapping from OID to Servant is present in the map or not. In the case of retain without a servant activator there is more of a question of when the servant can be deleted. But this is a problem in any case, and is the one that we have been discussing using reference counting to solve. In general the server developer is going to need to be careful in this case. And this case also is a problem for objects that are operands. (If I do reference_to_servant on an operand and then another thread deactivates the reference and deletes the servant I am screwed.) So, I think this proposal just adds complexity (both to the POA implementation and to the contract that POA users must understand) without really fixing a problem. A real fix to the problem won't need this change. > > > To "fix" this in general it will be necessary, during > deactivation, > to > > associate the ActiveObjectMap entry with all the requests in > operation > > at that time. (This is a lot harder than just counting the number > of > > requests outstanding for a particular servant.) The table entry > must > > then be held until all those requests finish. > > > > Not only does this seem absurdly complex and expensive, but is > harder to > > explain and use. When I deactivate something, I expect that it > will > no > > longer be active. > > It is neither absurdly complex nor expensive. It simply requires > keeping > track of the number of active requests per object. Upon deactivate > the > object is flagged so no new requests can be processed, and when the > request > count hits zero it is etherealized if necessary. I agree it is not absurdly complex or expensive to do what you suggested. I was proposing to solve the more general problem that is implied - to not deactivate any object that an executing request might depend on - is absurdly complex and expensive. > > > I realize the proposal doesn't ask for so much. But doing less > leads > to > > very inconsistent behavior. Assume the situation I started with: a > > request in one thread deactivates an object while another request > uses > > the same object. (In both cases the object is just data for the > request, > > not its target.) With your proposal, these threads would see the > object > > deactivation complete immediately. But if some other thread > happened > to > > be executing a request on the same object then they would see > different > > behavior. > > I'm a little confused by your example. If you are saying that > threads > would see different behavior based on the number of active requests, > then > I would say yes of course they do. If an object is deactivated and > there > are no active requests then its destruction is immediately apparent > (though > it may not yet be etherealized). If an object is deactivated and > there > are requests processing in that object, then the object's > deactivation > will not be apparent until all the requests executing in that object > have > completed. So the behavior will be different depending on the > situation, > but I think this is how it should be as these are two very different > situations. I am saying that requests that manipulate an object as an operand will see different behavior depending on whether or not there happens to be a concurrent invocation on the operand. > > > I don't see any reason to do anything special for these cases, > except > > what is already called regarding how _this() works in conjunction > with > > the current invocation context. > > I don't see why _this() should work for deactivated objects, but > calls > on the POA itself will not. This to me seems just as inconsistent > as > the problems you are complaining about in the proposal. _this already does a bunch of things in an invocation context that are different than when there is not an invocation context. I don't think anything more special is required here. If the object is deactivated, then _this should do more or less the same thing it does when a default_servant is used or a servant that has multiple activations. In all of these cases _this has to cook up a reference. Return-Path: Sender: "George Scott" Date: Tue, 14 Jul 1998 16:56:25 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Paul H Kyzivat CC: port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> Paul H Kyzivat wrote: > > > My point is that deactivating an object that is servicing an > invocation > is no worse (and no better) than deactivating an object that is > being > used as an operand by an invocation. Once the request has been > dispatched there is no longer any logical necessity for the object > to be > activated for the request to go to completion. This is not true, if the code defined in the method makes any POA calls it will see that it no longer exists and will most likely not behave correctly. The operations that have begun execution should be able to continue execution without any change in behavior. > Of course it would be bad for the servant to be deleted out from under > the method without its knowledge, but that is a separate issue. The > rules for etherealization already prevent the etherealization from > taking place until the invocation completes. So, when a ServantActivator > is present all we are talking about is whether the mapping from OID to > Servant is present in the map or not. > > In the case of retain without a servant activator there is more of a > question of when the servant can be deleted. But this is a problem in > any case, and is the one that we have been discussing using reference > counting to solve. In general the server developer is going to need to > be careful in this case. And this case also is a problem for objects > that are operands. (If I do reference_to_servant on an operand and then > another thread deactivates the reference and deletes the servant I am > screwed.) > > So, I think this proposal just adds complexity (both to the POA > implementation and to the contract that POA users must understand) > without really fixing a problem. A real fix to the problem won't need > this change. > Paul, could you please describe what you mean by a "real fix" to the problem. I'll be glad to hear it and discuss it. My goal here is to solve the problem, and if there is a better solution it would be good to know what it is so we can consider it. I agree that our proposed solution is not ideal, but it is the best one can do without major changes to the POA spec. > I am saying that requests that manipulate an object as an operand will > see different behavior depending on whether or not there happens to be a > concurrent invocation on the operand. Yes, this is correct. But as I said before these are different behaviors, so they have different results. The proposal is simply stating that an object cannot be deactivated while it is in use. So if it is in use, then it will still appear to be in the active object map, regardless if a call to the POA was made from the context of that object or not. This is completely consistent behavior. All threads will see the same behavior whether or not they are in a calling context. When there are no active requests they will see the object removed. There are no inconsistencies. > > > I don't see any reason to do anything special for these cases, > > except > > > what is already called regarding how _this() works in > conjunction > > with > > > the current invocation context. > > > > I don't see why _this() should work for deactivated objects, but > calls > > on the POA itself will not. This to me seems just as inconsistent > as > > the problems you are complaining about in the proposal. > > _this already does a bunch of things in an invocation context that > are > different than when there is not an invocation context. I don't > think > anything more special is required here. If the object is > deactivated, > then _this should do more or less the same thing it does when a > default_servant is used or a servant that has multiple > activations. In > all of these cases _this has to cook up a reference. This is not entirely true. It depends on how one implements _this(). In the Java mapping we have a strong binary compatibilty requirement so that all vendors can have binary compatibilty not just source compatibility. Because of this we have defined _this() to be a call to servant_to_reference on the current POA or the default POA for that servant. So the only way _this() can work correctly in Java is if servant_to_reference works correctly, or we abandon binary compatibilty in Java, so vendors may implement _this() in a proprietary fashion (and I can pretty much guarantee that won't happen). George Return-Path: Sender: "George Scott" Date: Tue, 14 Jul 1998 20:37:00 -0700 From: "George M. Scott" Organization: Inprise Corporation To: port-rtf@omg.org CC: gscott@inprise.com Subject: urgent POA issues Unfortunately, I missed all of the exciting debate on the port-rtf list last week, but I did notice a number of the most significant problems (IMHO) did not reach resolution. I think it is fairly important that we reach resolution on these for CORBA 2.3, as they fix a number of potentially serious problems that affect portability of multi-threaded or recursive POA programs. It seemed to me that we were very close to resolution and that if we can get agreement among the members of the POA RTF, we could then try and find a way to get the changes into CORBA 2.3 through some means (It's a shame that July is such a popular vacation month. ;-) ). The issues of concern are 1408, 1409, 1428, and 1627 (which was mistakenly transferred to the C++ RTF IMHO). I intend to send out concrete proposals for these issues in separate messages. If necessary I will reopen 1627 as a new issue, since it is not a language mapping issue, but a general POA issue. First let me summarize the problems and then provide some discussion: 1428 - blocking POA operations. This issue relates to potential deadlock situations in various ORB/POA calls which take a wait_for_completion parameter. It was not clear to me why this did not pass since it looked like there was consensus last Friday, and it should have been included in the RTF report. 1408/1409 - problems with destroy(). The behavior of destroy is not defined explicitly enough to guarantee consistency of programs. 1627 - problems with deactivate_object(). The behavior of deactivate_object is not defined explicitly enough to guarantee consistency of programs. Note the solution to this issue is parallel to the issue of 1408/1409. Also, a very important note, this issue has nothing to do with C++ memory management of servants, which is a separate language mapping specific issue and should be addressed in the C++ RTF (IMHO). I don't think we need much further discussion on 1428, so I mostly want to discuss destroy and deactivate_object which are essentially the same problem. The issue is when can an object be safely deactivated and when can a POA be safely destroyed. More importantly, when does the apparent destruction of the POA occur and when does the apparent deactivation of the object occur? Let's consider deactivate_object first because that is an easy case to illustrate the problems in the current spec. Imagine a server which represents millions of database records by encapsulating them in CORBA Objects. A servant activator is installed to incarnate and etherealize the objects as necessary. The CORBA server essentially serves as a cache for the database. Objects are periodically deactivated to conserve memory which results in etherealize being called and their current state being written back to the database. For improved startup time, a number of objects are pre-activated when the server is started by explicitly calling activate_object rather than wait for the ServantManager to create them. Now let's look at the problems in the current spec and what happens to database consistency, because deactivate_object semantics are not strong enough. Let's say there is an active object, A, which was explicitly activated by calling activate_object. The servant associated with object A is currently processing several requests for A, and the server decides it needs to persist A to the database because resources are running low. A thread in the server will call deactivate_object passing the id for A as an argument. According to the spec, A will immediately be removed from the active object map, but will not be etheralized until all current requests for A have completed. So we now have requests executing in an object which is not in the active object map and has not been etherealized meaning, its state is not in the database. There are many nasty scenarios which can now occur: - A new request arrives for A. The object is not in the active object map, so incarnate() is called on the ServantActivator. (Note, this does not violate the rules for serialization of ServantActivators which state that incarnation may not overlap for objects which were incarnated by a ServantActivator because the original object A was activated explicitly using activate_object.) Because A is still in the server and has not been etherealized, a "stale" version of A will be incarnated from the database, which we will call A'. Eventually the requests executing in A will complete and A will be etherealized to the database. When A' is etherealized it will overwrite A. The database is now most likely completely inconsistent. - Now consider what happens to requests that are executing in A after A has been deactivated. If they call any POA operation which requires the use of the active object map (i.e. the RETAIN policy), they will get the incorrect result. For instance, if they call id_to_servant they may get ObjectNotActive, however if the A' in the above scenario has already been created they may get the Servant for A' which will most likely be different than the Servant for A. The results could be disastorous for the application. There are many variations on the above scenarios which can all occur because the apparent deactivation of an object occured before it should have. With the current model users will have to always be prepared to handle this strange behavior in all user code. This will make development of CORBA components which can be dynamically managed in memory by intelligent application servers very difficult if not impossible. Users will have to modify their code to handle the incosistent behavior and such modification will most likely be dependent on the particular server in which a CORBA component is being deployed. We may as well just give the market to Microsoft now, and not waste our time. All dramatics aside, this is a serious problem which needs to be addressed and very soon in my opinion. Now if it isn't clear already, the POA destroy operation has the exact same problem. If the server were to manage objects by destroying entire POAs instead of individual objects then it is possible to have a POA B and a POA B' in existence at the same time. And not only have a single object inconsistent but an entire set of objects managed by that POA totally inconsistent. I'm sure that will sell a lot of POA implementations.... So here are the requirements as we see them: 1. Etherealize may only be called for an object which has no currently executing requests. 2. Apparent destruction of a POA or deactivation of an object does not occur until all active requests in that POA or object have completed. 3. After destruction or deactivation has commenced no new requests can begin processing until destruction or deactivation has completed. 4. The system should not deadlock even in the presence of recursive calls across multiple servers. Our proposal satisifies all of the above requirements without changing any POA APIs or drastically changing behavior. In all cases the POA behavior is merely clarified and made more explicit so programs may be written in a portable fashion. Let's look at each in more detail: 1. Etheralization may only occur after all requests have completed. This is what the current spec states and we do not intend to change this behavior. (We take back what we said in our earlier proposal) 2. Apparent destruction/deactivation occurs after all requests have completed. Today the spec only states that apparent destruction occurs before etherealization is called. Since etherealization is called after all requests have completed, this change is consistent with the current spec, but adds a stronger requirement that apparent destruction must not occur until all active requests have completed. So this change strengthens the semantics of the spec, but does not change or weaken the current semantics. 3. After destruction or deactivation no new requests can begin. This is also consistent with the current spec, though it does result in a creation which is delayed because the apparent destruction (#2 above) may be delayed due to active requests. 4. Deadlocks should not occur. Now, I will be the first to admit that this is nearly impossible to prove in a complex distributed system. But I would like to eliminate the obvious ones. Our previous proposals could deadlock because two objects in two different processes could have a mutual recursion which could result in deadlock. For example object A could call object B in another server, object B then attempts to call object A again. However, right before object B calls object A another thread in object A's server attempts to deactivate A or destroy A's POA. This will result in deadlock because our previous proposal would act as if the POA's POAManager was in the holding state which will queue requests and hence block, resulting in deadlock. Our new proposal states that the object will behave as if it is in the discarding state which means it will not queue the request but instead throw the TRANSIENT exception. What a client ORB or application does with TRANSIENT is not currently defined in any CORBA spec, but it does say the request should be reissued. So an ORB may simply repeatedly reissue the request resulting in a livelock, or it may be intelligent and realize that after five minutes of receiving transients it may as well give up. This is implementation dependent but the important thing is that the ORB/application is deadlock free and whether or not it will make progress or livelock is an implementation decision that vendors may choose to make. Before anybody screams about this please remember that whether or not applications deadlock in CORBA today (even with the POA) is dependent on the server's thread model. A single threaded ORB will always deadlock in the above scenario because it can't handle distributed mutual recursion. A multi- threaded ORB with a fixed size thread pool will deadlock when it runs out of threads. All we are trying to accomplish is to allow a well written ORB/POA to not deadlock even in the most extreme cases. We believe this is possible, and the spec should allow for such implementations. Now there are a few improvements we can also make to help this new model out a little bit. For example, if an object is being deactivated but it has the policy USE_ACTIVE_OBJECT_MAP_ONLY (the default policy) then it is possible to actual behave as if the POA were in the inactive state and immediately throw OBJECT_NOT_EXIST. Similiarly if a POA is destroyed and its parent does not have an adapter activator then it is also possible to immediately return an OBJECT_NOT_EXIST because the POA will not be automatically created after it is destroyed and OBJECT_NOT_EXIST will be the result. This will handle a lot of the common cases and improve performance because the requests will not need to be reissued. As I said previously I will send out our proposals in separate messages. We would greatly appreciate feedback as soon as possible and would like to build consensus behind a solution to this problem this week be it our solution or any other proposed solution. Thanks. George Return-Path: Sender: "George Scott" Date: Tue, 14 Jul 1998 20:39:24 -0700 From: "George M. Scott" Organization: Inprise Corporation To: port-rtf@omg.org CC: gscott@inprise.com Subject: Proposal for issue 1627 Fire away... Issue 1627: Problems with deactivate_object() Nature: Revision Summary: deactivate_object behavior is not defined when multiple concurrent active requests are executing in an object when it is deactivated. Resolution: Accepted for Corba RTF 2.3 Revision: Replace the second paragraph describing deactivate_object on page 9-35, section 9.3.8 with the following: This operation causes the ObjectId specified in the oid parameter to be deactivated. An ObjectId which has been deactivated cannot receive new requests until the ObjectId has been removed from the Active Object Map. Any new requests which arrive for a deactivated ObjectId will behave as if the POA's POAManager was in the inactive state if the RequestProcessingPolicy is USE_ACTIVE_OBJECT_MAP_ONLY, otherwise they will behave as if the POA's POAManager were in the discarding state. A deactivated ObjectId is removed from the Active Object Map when all requests executing for that ObjectId have completed. If a servant manager is associated with the POA, ServantActivator::etherealize will be invoked with the oid and the associated servant after the ObjectId has been removed from the Active Object Map. Once an ObjectId has been removed from the Active Object Map and etherealized (if necessary) it may then be reactivated through the usual mechanisms. The operation does not wait for requests or etherealization to complete and always returns immediately after deactivating the ObjectId. Return-Path: Date: Wed, 15 Jul 1998 16:46:35 -0400 From: Paul H Kyzivat Organization: NobleNet To: "George M. Scott" CC: port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> George M. Scott wrote: > > Paul H Kyzivat wrote: > > > > > > My point is that deactivating an object that is servicing an > invocation > > is no worse (and no better) than deactivating an object that is > being > > used as an operand by an invocation. Once the request has been > > dispatched there is no longer any logical necessity for the object > to be > > activated for the request to go to completion. > > This is not true, if the code defined in the method makes any POA > calls it will see that it no longer exists and will most likely not > behave correctly. The operations that have begun execution should > be > able to continue execution without any change in behavior. But doing operations on the POA relative to the activation of the servant is entirely optional. Most often this is not needed. The cases when it is necessary are really quite unusual. > > > Of course it would be bad for the servant to be deleted out from > under > > the method without its knowledge, but that is a separate > issue. The > > rules for etherealization already prevent the etherealization from > > taking place until the invocation completes. So, when a > ServantActivator > > is present all we are talking about is whether the mapping from > OID > to > > Servant is present in the map or not. > > > > In the case of retain without a servant activator there is more of > a > > question of when the servant can be deleted. But this is a problem > in > > any case, and is the one that we have been discussing using > reference > > counting to solve. In general the server developer is going to > need > to > > be careful in this case. And this case also is a problem for > objects > > that are operands. (If I do reference_to_servant on an operand and > then > > another thread deactivates the reference and deletes the servant I > am > > screwed.) > > > > So, I think this proposal just adds complexity (both to the POA > > implementation and to the contract that POA users must understand) > > without really fixing a problem. A real fix to the problem won't > need > > this change. > > > > Paul, could you please describe what you mean by a "real fix" to the > problem. I'll be glad to hear it and discuss it. My goal here is > to > solve the problem, and if there is a better solution it would be > good > to know what it is so we can consider it. I agree that our proposed > solution is not ideal, but it is the best one can do without major > changes to the POA spec. The reference counting proposal is what is required in order to guarantee that a servant isn't deleted unexpectedly out from under code that is using it - whether that is a method dispatched to it or a piece of code that has done id_to_servant (or reference_to_servant or get_servant) and is trying to use the returned servant for something. This is the "real fix" for the problem that needs fixing. The other case (I guess the one that bothers you) is servant_to_reference. As far as I am concerned, if a server activates an object with a servant, then deactivates it, it should not expect servant_to_reference to return a reference to the now-deactivated object. However there has been a proposal that servant_to_reference should always take into account the servant for the current invocation context (if any) and in that case use the id from the invocation context to construct the reference. I could live with that. > > > I am saying that requests that manipulate an object as an operand > will > > see different behavior depending on whether or not there happens > to > be a > > concurrent invocation on the operand. > > Yes, this is correct. But as I said before these are different > behaviors, > so they have different results. > > The proposal is simply stating that an object cannot be deactivated > while > it is in use. So if it is in use, then it will still appear to be > in > the > active object map, regardless if a call to the POA was made from the > context of that object or not. This is completely consistent > behavior. > All threads will see the same behavior whether or not they are in a > calling context. When there are no active requests they will see > the > object removed. There are no inconsistencies. You and I seem to have different notions of what it means for an object to be "in use". I gather you consider it to be in use only when it has been selected as the target of an in-progress invocation. I consider this to just be a special case of some piece of server code manipulating an oid or servant for what it believes to be an activated object. In particular the example above of server code calling id_to_servant puts that object into use just as surely as does an invocation on the object. But your proposal does not deal with this other kind of use. For a concrete example: Suppose we have a factory object that creates and returns references to other objects, like CosNaming::NamingContext::new_context to be specific. Perhaps the implementation of new_context decides to do something like the following (crude pseudo-code): ctx_servant = new ContextImpl(); poa->activate_object(ctx_servant); // 1 return ctx_servant->_this(); At point 1 it is possible that another thread in the server decides to deactivate this object. If there is a servant activator, etherealize will be called, and since there are no invocations of this object in progress it may well decide to delete the servant. Then the call to _this will crash in flames. The proposal doesn't fix this because it doesn't consider the object to be "in use" here. > > > > > I don't see any reason to do anything special for these cases, > > > except > > > > what is already called regarding how _this() works in > conjunction > > > with > > > > the current invocation context. > > > > > > I don't see why _this() should work for deactivated objects, but > calls > > > on the POA itself will not. This to me seems just as > inconsistent > as > > > the problems you are complaining about in the proposal. > > > > _this already does a bunch of things in an invocation context that > are > > different than when there is not an invocation context. I don't > think > > anything more special is required here. If the object is > deactivated, > > then _this should do more or less the same thing it does when a > > default_servant is used or a servant that has multiple > activations. > In > > all of these cases _this has to cook up a reference. > > This is not entirely true. It depends on how one implements > _this(). > In the Java mapping we have a strong binary compatibilty requirement > so that all vendors can have binary compatibilty not just source > compatibility. Because of this we have defined _this() to be a call > to servant_to_reference on the current POA or the default POA for > that > servant. So the only way _this() can work correctly in Java is if > servant_to_reference works correctly, or we abandon binary > compatibilty > in Java, so vendors may implement _this() in a proprietary fashion > (and > I can pretty much guarantee that won't happen). My first reaction to this was to consider that the java mapping might be broken. I don't think we are obligated to fix the POA spec to deal with that. The change proposed by someone to make servant_to_reference consider the current invocation context would solve this problem. A change to POACurrent to provide access to the servant would also allow you to implement _this() to handle this case. Either of these would be preferable (in my opinion) to the proposal we are discussing. Return-Path: Date: Wed, 15 Jul 1998 16:59:45 -0400 From: Paul H Kyzivat Organization: NobleNet To: Jonathan Biggar CC: "George M. Scott" , port-rtf@omg.org, issues@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> <35A39D6F.879ACFE4@noblenet.com> <35A3A2D6.B0277A5B@floorboard.com> Jonathan Biggar wrote: > I see this as a general robustness issue. If I have to write all of > my > operation implementations with the idea that anyone can deactivate > the > object at anytime while I am in progress, I have to write a whole > lot > more code to handle this case. It's much easier for the ORB to make > sure of this than for my application code to do so. I am all in favor of robustness, and this proposal doesn't provide it. See my recent reply to George Scott on the same subject - particularly the example. > Sure it's legal C++, but the current spec is entirely broken. Any > operation implementation that calls deactivate_object() followed by > deleting this, as the POA is currently specified is simply a core > dump > waiting to happen in a multithreaded environment. We must fix this, > as > quickly as possible, or we might as well consider the POA > specification > a failure. I agree with you on this - but apparently not on what a necessary and sufficient fix is. Keeping the id/servant in the map until the operation returns isn't going to solve this problem. In general there is no solution that doesn't potentially involve a wait or a (possibly delayed) call to etherealize, or reference counting. Waiting and etherealization are already available. I don't believe we need new ways to wait. Reference counting is all that is left. > > > With the proposed change, it would appear that another operation > that > > happens to be in progress at the same time will be able to call > > id_to_servant after the deactivation and still be handed the > servant > > that is about to destroy itself. This makes the problem of knowing > when > > a servant is valid worse rather than better. > > This change is part of the package. In itself, it doesn't fix the > problem with servant destruction, but paired with the appropriate > language mapping solution (reference counts) it plugs the hole. If you provide the reference counts, you don't also need this change. Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Thu, 16 Jul 1998 07:10:30 +1000 (EST) From: Michi Henning To: Paul H Kyzivat cc: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() Content-ID: On Wed, 15 Jul 1998, Paul H Kyzivat wrote: > But your proposal does not deal with this other kind of use. > > For a concrete example: > > Suppose we have a factory object that creates and returns references > to > other objects, like CosNaming::NamingContext::new_context to be > specific. Perhaps the implementation of new_context decides to do > something like the following (crude pseudo-code): > > ctx_servant = new ContextImpl(); > poa->activate_object(ctx_servant); > // 1 > return ctx_servant->_this(); > > At point 1 it is possible that another thread in the server decides > to > deactivate this object. If there is a servant activator, etherealize > will be called, and since there are no invocations of this object in > progress it may well decide to delete the servant. Then the call to > _this will crash in flames. The proposal doesn't fix this because it > doesn't consider the object to be "in use" here. If this happens, I would have argued that the server code has a bug. In my opinion, the server writer is responsible for ensuring that no other thread can delete the servant at point (1). The above code should hold a lock from where it creates the servant until after it has created the reference for the servant. I don't think any amount of tinkering with the POA can ever to this work for the server writer automatically, simply because exactly when it is safe to allow another thread to see the object and act on it is higly specific to the application. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: Sender: jon@floorboard.com Date: Wed, 15 Jul 1998 14:10:54 -0700 From: Jonathan Biggar To: "George M. Scott" CC: port-rtf@omg.org Subject: Re: Proposal for issue 1627 References: <35AC246C.F6B72C08@inprise.com> George M. Scott wrote: > > Fire away... > > Issue 1627: Problems with deactivate_object() > Nature: Revision > > Summary: deactivate_object behavior is not defined when multiple > concurrent active requests are executing in an object > when it is deactivated. > > Resolution: Accepted for Corba RTF 2.3 > > Revision: Replace the second paragraph describing deactivate_object > on page 9-35, section 9.3.8 with the following: > > This operation causes the ObjectId specified in the oid parameter to > be deactivated. An ObjectId which has been deactivated cannot > receive > new requests until the ObjectId has been removed from the Active > Object Map. Any new requests which arrive for a deactivated ObjectId > will behave as if the POA's POAManager was in the inactive state if > the RequestProcessingPolicy is USE_ACTIVE_OBJECT_MAP_ONLY, otherwise > they will behave as if the POA's POAManager were in the discarding > state. A deactivated ObjectId is removed from the Active Object Map > when all requests executing for that ObjectId have completed. If a > servant manager is associated with the POA, > ServantActivator::etherealize > will be invoked with the oid and the associated servant after the > ObjectId has been removed from the Active Object Map. Once an > ObjectId has been removed from the Active Object Map and > etherealized > (if necessary) it may then be reactivated through the usual > mechanisms. > > The operation does not wait for requests or etherealization to > complete and always returns immediately after deactivating the > ObjectId. I agree we accidentally tried to shift this one to the C++ RTF. However, the vote failed due to lack of quorum, so we are still stuck with this one. :-) This proposal (and the proposals for 1409 & 1409) failed to reach consensus on Friday, due to the requirement for the discarding state. Quite a bit of sentiment was expressed that this was bad and that we should look for a solution that was more transparent to clients. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: jon@floorboard.com Date: Wed, 15 Jul 1998 14:31:33 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> Paul H Kyzivat wrote: > > This is not true, if the code defined in the method makes any POA > > calls it will see that it no longer exists and will most likely > not > > behave correctly. The operations that have begun execution should > be > > able to continue execution without any change in behavior. > > But doing operations on the POA relative to the activation of the > servant is entirely optional. Most often this is not needed. The > cases > when it is necessary are really quite unusual. Right. Why call id_to_servant(), for example, when you already have the servant in hand. > The other case (I guess the one that bothers you) is > servant_to_reference. As far as I am concerned, if a server > activates an > object with a servant, then deactivates it, it should not expect > servant_to_reference to return a reference to the now-deactivated > object. However there has been a proposal that servant_to_reference > should always take into account the servant for the current > invocation > context (if any) and in that case use the id from the invocation > context > to construct the reference. I could live with that. Right. Since the POA must already know the servant and the OID (to implement PortableServer::Current) it should be able to construct the reference without accessing the active object map. (In fact it already needs to be able to do so for use with default servants or servant locators.) > For a concrete example: > > Suppose we have a factory object that creates and returns references > to > other objects, like CosNaming::NamingContext::new_context to be > specific. Perhaps the implementation of new_context decides to do > something like the following (crude pseudo-code): > > ctx_servant = new ContextImpl(); > poa->activate_object(ctx_servant); > // 1 > return ctx_servant->_this(); > > At point 1 it is possible that another thread in the server decides > to > deactivate this object. If there is a servant activator, etherealize > will be called, and since there are no invocations of this object in > progress it may well decide to delete the servant. Then the call to > _this will crash in flames. The proposal doesn't fix this because it > doesn't consider the object to be "in use" here. This is one of the reasons why I now consider reference counting as the only viable solution. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Wed, 15 Jul 1998 18:54:35 -0400 From: Paul H Kyzivat Organization: NobleNet To: "George M. Scott" CC: port-rtf@omg.org Subject: Re: urgent POA issues References: <35AC23DC.7B2F1ECF@inprise.com> George M. Scott wrote: > Imagine a server which represents millions of database records by > encapsulating them in CORBA Objects. A servant activator is > installed > to incarnate and etherealize the objects as necessary. The CORBA > server essentially serves as a cache for the database. Objects are > periodically deactivated to conserve memory which results in > etherealize being called and their current state being written back > to > the database. For improved startup time, a number of objects are > pre-activated when the server is started by explicitly calling > activate_object rather than wait for the ServantManager to create > them. I presume you are assuming a UNIQUE_ID policy so that a given servant is associated with at most one object. > > Now let's look at the problems in the current spec and what happens > to > database consistency, because deactivate_object semantics are not > strong enough. Let's say there is an active object, A, which was > explicitly activated by calling activate_object. The servant > associated with object A is currently processing several requests > for > A, and the server decides it needs to persist A to the database > because resources are running low. A thread in the server will call > deactivate_object passing the id for A as an argument. According to > the spec, A will immediately be removed from the active object map, > but will not be etheralized until all current requests for A have > completed. So we now have requests executing in an object which is > not in the active object map and has not been etherealized meaning, > its state is not in the database. There are many nasty scenarios > which can now occur: > > - A new request arrives for A. The object is not in the active > object map, > so incarnate() is called on the ServantActivator. (Note, this > does > not > violate the rules for serialization of ServantActivators which > state that > incarnation may not overlap for objects which were incarnated by > a > ServantActivator because the original object A was activated > explicitly > using activate_object.) Because A is still in the server and has > not > been etherealized, a "stale" version of A will be incarnated from > the > database, which we will call A'. Eventually the requests > executing > in > A will complete and A will be etherealized to the database. When > A' > is etherealized it will overwrite A. The database is now most > likely completely inconsistent. OK, I think I see your problem. The spec implied to me (although it isn't explicit) that the serialization of incarnate and etherealize must extent to stalling a subsequent incarnation while an etherealization is pending for the same objectId. This is different than requiring the object to remain active until the etherealization begins - tests for the presence of the object can still fail (because it has been deactivated) and an explict activation is OK. > > - Now consider what happens to requests that are executing in A > after > A has been deactivated. If they call any POA operation which > requires > the use of the active object map (i.e. the RETAIN policy), they > will > get the incorrect result. For instance, if they call > id_to_servant > they may get ObjectNotActive, however if the A' in the above > scenario > has already been created they may get the Servant for A' which > will > most likely be different than the Servant for A. The results > could > be disastorous for the application. Given the interpretation I gave above, there would be no A' while there are requests executing in A. It indeed might be the case that id_to_servant would fail. This has nothing to do with the timing of etherealization - it only has to do with explicit multithreading code written by the developer. Why should it succeed? It is unwise to be be writing code that depends on activations in a POA while at the same time writing concurrent code that removes them. And this isn't a hard thing to avoid in this case since the servant ought to already know who it is, or it can find out from POACurrent. > > There are many variations on the above scenarios which can all occur > because the apparent deactivation of an object occured before it > should have. With the current model users will have to always be > prepared to handle this strange behavior in all user code. This > will > make development of CORBA components which can be dynamically > managed > in memory by intelligent application servers very difficult if not > impossible. There are (at least) three things going on here: - removal of the oid:servant association from the map - etherealization of the oid:servant association - deletion of the servant No matter what we do, all of these need to be dealt with, and these may all occur at (more-or-less) the same time, or at widely spaced times, or not at all, in various combinations. The existing policies make some combinations easier to use than others. You are not going to get agreement about when these things "should" occur because there is no one answer. You seem to think that one particular combination of interest to you is not currently supported (or at least isn't easily used), and are also proposing that another combination that is currently allowed is bad or useless and should be replaced by the one you want. These things should be separate considerations. If some feature is without merit then we should perhaps consider removing it. If what you want is not currently possible AND is important then we should consider adding it. > Users will have to modify their code to handle the > incosistent behavior and such modification will most likely be > dependent on the particular server in which a CORBA component is > being > deployed. We may as well just give the market to Microsoft now, and > not waste our time. All dramatics aside, this is a serious problem > which > needs to be addressed and very soon in my opinion. Inconsistency is yet another issue. I agree that we should be clear about what the user can expect, and that this contract should be sufficient for use. On the other hand, one of the most important (and hardest) things a standard must do is decide what does not need to be standardized. There must not be needless restrictions that prevent ORB implementors from making implementation decisions. It is perfectly acceptable for a standard to say that some aspect of behavior is explicitly undefined. The problems come when some people think a behavior is defined and others think it is not. > > Now if it isn't clear already, the POA destroy operation has the > exact > same > problem. If the server were to manage objects by destroying entire > POAs > instead of individual objects then it is possible to have a POA B > and > a POA > B' in existence at the same time. And not only have a single object > inconsistent but an entire set of objects managed by that POA > totally > inconsistent. I'm sure that will sell a lot of POA > implementations.... The analogy isn't perfect. In the case of POAs, the only thing that is ever explicitly visible is a reference to a POA - there are no visible POA servants (though they may exist in a particular ORB implementation.) Just as a regular object reference remains invariant though it may map to different servants from time to time, a reference to a POA should also remain invariant though it may refer to a different incarnation of that POA from time to time. So it should never appear as if there is both a B and a B'. > > So here are the requirements as we see them: [snip] > Our proposal satisifies all of the above requirements without > changing > any POA APIs or drastically changing behavior. In all cases the POA > behavior is merely clarified and made more explicit so programs may > be > written in a portable fashion. > > Let's look at each in more detail: > > 1. Etheralization may only occur after all requests have completed. > This is > what the current spec states and we do not intend to change this > behavior. > (We take back what we said in our earlier proposal) No problem here. > > 2. Apparent destruction/deactivation occurs after all requests have > completed. > Today the spec only states that apparent destruction occurs > before > etherealization is called. Since etherealization is called after > all > requests have completed, this change is consistent with the > current > spec, but adds a stronger requirement that apparent destruction > must not > occur until all active requests have completed. So this change > strengthens > the semantics of the spec, but does not change or weaken the > current > semantics. I agree for the POA because it is the *implementation* of the POA that mediates requests and that is being destroyed. I disagree for deactivation for reasons stated here and in other replies. > > 3. After destruction or deactivation no new requests can begin. > This > is > also consistent with the current spec, though it does result in a > creation > which is delayed because the apparent destruction (#2 above) may > be > delayed due to active requests. In the case of POA destruction I agree. In the case of deactivation see my comments elsewhere. > > 4. Deadlocks should not occur. Now, I will be the first to admit > that > this > is nearly impossible to prove in a complex distributed system. This is a nice goal, but it is unachievable. Deadlock detection would at best be very expensive. Deadlock prevention in all cases requires imposition of rules that prevent reasonable usage. I think all we can do is ensure that deadlocks are not a direct consequence of reasonable and common usage, and make it relatively easy for a developer to figure out what kinds of behavior might lead to deadlock. In practical cases it is pretty easy to avoid deadlock for the particular circumstances of any specific server. > But I would > like to eliminate the obvious ones. Our previous proposals could > deadlock > because two objects in two different processes could have a > mutual > recursion which could result in deadlock. For example object A > could call > object B in another server, object B then attempts to call object > A > again. > However, right before object B calls object A another thread in > object > A's server attempts to deactivate A or destroy A's POA. This > will > result > in deadlock because our previous proposal would act as if the > POA's > POAManager was in the holding state which will queue requests and > hence > block, resulting in deadlock. Our new proposal states that the > object > will behave as if it is in the discarding state which means it > will > not > queue the request but instead throw the TRANSIENT exception. I don't think deadlocks of this sort are a big issue, because hardly anyone is going to destroy POAs dynamically and to do so in conjunction with mutual recursion would be remarkable. That said, I would rather risk the deadlock than throw away the requests. If somebody wants this kind of behavior they can first set the POAs POAManager to discarding and then destroy the POA. > > What a client ORB or application does with TRANSIENT is not > currently > defined in any CORBA spec, but it does say the request should be > reissued. > So an ORB may simply repeatedly reissue the request resulting in > a > livelock, or it may be intelligent and realize that after five > minutes > of receiving transients it may as well give up. This is I don't think the spec mandates that an ORB should automatically retry a request when a transient exception is received. I don't even think it is a good idea. Unless or until it is clear that this is required behavior we should assume that an ORB client is going to get the exception and have to deal with it explicitly - it is going to bother somebody. > implementation > dependent but the important thing is that the ORB/application is > deadlock > free and whether or not it will make progress or livelock is an > implementation decision that vendors may choose to make. Before > anybody > screams about this please remember that whether or not > applications > deadlock in CORBA today (even with the POA) is dependent on the > server's > thread model. A single threaded ORB will always deadlock in the > above > scenario because it can't handle distributed mutual recursion. A > multi- > threaded ORB with a fixed size thread pool will deadlock when it > runs out > of threads. > All we are trying to accomplish is to allow a well > written > ORB/POA to not deadlock even in the most extreme cases. We > believe > this > is possible, and the spec should allow for such implementations. Explicit deactivation of the POAManager prior to destruction will handle this. > > Now there are a few improvements we can also make to help this > new > model > out a little bit. For example, if an object is being deactivated > but > it has the policy USE_ACTIVE_OBJECT_MAP_ONLY (the default policy) > then > it is possible to actual behave as if the POA were in the > inactive > state and immediately throw OBJECT_NOT_EXIST. > > Similiarly if a POA is destroyed and its parent does not have an > adapter activator then it is also possible to immediately return > an > OBJECT_NOT_EXIST because the POA will not be automatically > created > after > it is destroyed and OBJECT_NOT_EXIST will be the result. > > This will handle a lot of the common cases and improve > performance > because > the requests will not need to be reissued. > > As I said previously I will send out our proposals in separate > messages. > We would greatly appreciate feedback as soon as possible and would > like to > build consensus behind a solution to this problem this week be it > our > solution or any other proposed solution. I will try to reply to the specific proposals, but consider this message as context and partial reply to them. Return-Path: Sender: "George Scott" Date: Wed, 15 Jul 1998 20:52:28 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Paul H Kyzivat CC: port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> Paul H Kyzivat wrote: > > George M. Scott wrote: > > > > > > Paul, could you please describe what you mean by a "real fix" to > the > > problem. I'll be glad to hear it and discuss it. My goal here is > to > > solve the problem, and if there is a better solution it would be > good > > to know what it is so we can consider it. I agree that our > proposed > > solution is not ideal, but it is the best one can do without major > > changes to the POA spec. > > The reference counting proposal is what is required in order to > guarantee that a servant isn't deleted unexpectedly out from under > code > that is using it - whether that is a method dispatched to it or a > piece > of code that has done id_to_servant (or reference_to_servant or > get_servant) and is trying to use the returned servant for > something. > This is the "real fix" for the problem that needs fixing. Again, the proposal is not addressing the issue of memory management this is a completely orthogonal issue. > The other case (I guess the one that bothers you) is > servant_to_reference. As far as I am concerned, if a server > activates an > object with a servant, then deactivates it, it should not expect > servant_to_reference to return a reference to the now-deactivated > object. However there has been a proposal that servant_to_reference > should always take into account the servant for the current > invocation > context (if any) and in that case use the id from the invocation > context > to construct the reference. I could live with that. It's not just servant_to_reference, it is all of the *_to_* conversions which use the active object map where * is one of servant, reference, or id. You can make all of these context sensitive, but it is not necessary if you simply enfore the simple rule which is an object may not be removed from the map when requests are active. Once the object it is out of the map, it may be recreated and there will be two instances of the same object living in the POA and this is not a good thing. > > The proposal is simply stating that an object cannot be deactivated > > while > > it is in use. So if it is in use, then it will still appear to be in > > the > > active object map, regardless if a call to the POA was made from the > > context of that object or not. This is completely consistent > > behavior. > > All threads will see the same behavior whether or not they are in a > > calling context. When there are no active requests they will see the > > object removed. There are no inconsistencies. > > You and I seem to have different notions of what it means for an object > to be "in use". I gather you consider it to be in use only when it has > been selected as the target of an in-progress invocation. Correct. > I consider this to just be a special case of some piece of server code > manipulating an oid or servant for what it believes to be an activated > object. In particular the example above of server code calling > id_to_servant puts that object into use just as surely as does an > invocation on the object. > > But your proposal does not deal with this other kind of use. > > For a concrete example: > > Suppose we have a factory object that creates and returns references to > other objects, like CosNaming::NamingContext::new_context to be > specific. Perhaps the implementation of new_context decides to do > something like the following (crude pseudo-code): > > ctx_servant = new ContextImpl(); > poa->activate_object(ctx_servant); > // 1 > return ctx_servant->_this(); > > At point 1 it is possible that another thread in the server decides to > deactivate this object. If there is a servant activator, etherealize > will be called, and since there are no invocations of this object in > progress it may well decide to delete the servant. Then the call to > _this will crash in flames. The proposal doesn't fix this because it > doesn't consider the object to be "in use" here. Again, you are confusing the memory management issue with my proposal. In my proposal, when you call _this() it would throw an exception because the object is no longer active, not core dump. For example, in Java you still have a reference to the object so it cannot be garbage collected. If reference counting were properly implemented for Servants in the c++ mapping of the POA, then your servant would presumably have a ref of 1 even after _this() was called, and would not be deleted until you unrefed it. > My first reaction to this was to consider that the java mapping might be > broken. I don't think we are obligated to fix the POA spec to deal with > that. No, but then the Java mapping would be obligated to add a speical POA operation for the Java mapping only to solve this problem. > The change proposed by someone to make servant_to_reference consider the > current invocation context would solve this problem. > > A change to POACurrent to provide access to the servant would also allow > you to implement _this() to handle this case. > > Either of these would be preferable (in my opinion) to the proposal we > are discussing. These still do not prevent multiple copies of the same object from running at the same time. George Return-Path: Sender: "George Scott" Date: Wed, 15 Jul 1998 20:55:23 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Jonathan Biggar CC: Paul H Kyzivat , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD1FB5.5C61EB02@floorboard.com> Jonathan Biggar wrote: > > Paul H Kyzivat wrote: > > > This is not true, if the code defined in the method makes any > POA > > > calls it will see that it no longer exists and will most likely > not > > > behave correctly. The operations that have begun execution > should be > > > able to continue execution without any change in behavior. > > > > But doing operations on the POA relative to the activation of the > > servant is entirely optional. Most often this is not needed. The > cases > > when it is necessary are really quite unusual. > > Right. Why call id_to_servant(), for example, when you already have > the > servant in hand. A simple example is if you implemented your servant using a tie. Your tie object may need to get access to the servant for some reason so it could use this mechanism. This of course is not the most efficient way of doing this, but is allowed. George Return-Path: Sender: "George Scott" Date: Wed, 15 Jul 1998 21:08:19 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Paul H Kyzivat CC: Jonathan Biggar , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> <35A39D6F.879ACFE4@noblenet.com> <35A3A2D6.B0277A5B@floorboard.com> <35AD1841.37EF0352@noblenet.com> Paul H Kyzivat wrote: > > Jonathan Biggar wrote: > > > I see this as a general robustness issue. If I have to write all > of > > my > > operation implementations with the idea that anyone can deactivate > the > > object at anytime while I am in progress, I have to write a whole > lot > > more code to handle this case. It's much easier for the ORB to > make > > sure of this than for my application code to do so. > > I am all in favor of robustness, and this proposal doesn't provide > it. > See my recent reply to George Scott on the same subject - > particularly > the example. The proposal is robust for the problem it is trying to solve. It is not trying to solve the C++ memory management issue. The POA and the proposal work great for garbage collected languages, such as Java. Memory management has always been a language mapping issue, so I don't see why it is any different for POA Servants. If there is a robustness problem with C++ programs and the POA it should be solved in the C++ RTF as necessary. > > Sure it's legal C++, but the current spec is entirely broken. Any > > operation implementation that calls deactivate_object() followed > by > > deleting this, as the POA is currently specified is simply a core > dump > > waiting to happen in a multithreaded environment. We must fix > this, > > as > > quickly as possible, or we might as well consider the POA > > specification > > a failure. > > I agree with you on this - but apparently not on what a necessary > and > sufficient fix is. Keeping the id/servant in the map until the > operation > returns isn't going to solve this problem. > > In general there is no solution that doesn't potentially involve a > wait > or a (possibly delayed) call to etherealize, or reference counting. > Waiting and etherealization are already available. I don't believe > we > need new ways to wait. Reference counting is all that is left. I hate to keep repeating myself. But the proposal is not attempting to solve the memory management problem. The solution for that requires a change to the C++ language mapping, not the POA. > > > > This change is part of the package. In itself, it doesn't fix the > > problem with servant destruction, but paired with the appropriate > > language mapping solution (reference counts) it plugs the hole. > > If you provide the reference counts, you don't also need this > change. Wrong. This change solves a different unrelated problem. Paul, I understand that you want a fix to the "complete" solution of deactivating objects. There are several problems that have been pointed out in the current spec. I'm trying to solve only one of them. The portability group agreed to transfer the C++ memory management issues to the C++ RTF as part of its report (ptc/98-07-01). It will require a change to the C++ mapping to provide a "complete" solution for that language. Java for instance, does not have this problem, because it has garbage collection. However it does have other problems which my proposal is attempting to solve. These problems are generic in nature and not related to the language mapping. Only through fixing the problems I have raised as well as the C++ issues others have raised can we get to a "complete" solution, IMHO. George Return-Path: Date: Thu, 16 Jul 1998 08:36:43 -0400 From: Paul H Kyzivat Organization: NobleNet To: Michi Henning CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: Michi Henning wrote: > > On Wed, 15 Jul 1998, Paul H Kyzivat wrote: > > > But your proposal does not deal with this other kind of use. > > > > For a concrete example: > > > > Suppose we have a factory object that creates and returns > references > to > > other objects, like CosNaming::NamingContext::new_context to be > > specific. Perhaps the implementation of new_context decides to do > > something like the following (crude pseudo-code): > > > > ctx_servant = new ContextImpl(); > > poa->activate_object(ctx_servant); > > // 1 > > return ctx_servant->_this(); > > > > At point 1 it is possible that another thread in the server > decides > to > > deactivate this object. If there is a servant activator, > etherealize > > will be called, and since there are no invocations of this object > in > > progress it may well decide to delete the servant. Then the call > to > > _this will crash in flames. The proposal doesn't fix this because > it > > doesn't consider the object to be "in use" here. > > If this happens, I would have argued that the server code has a bug. > In my opinion, the server writer is responsible for ensuring that > no other thread can delete the servant at point (1). The above code > should hold a lock from where it creates the servant until after it > has created the reference for the servant. > > I don't think any amount of tinkering with the POA can ever to this > work > for the server writer automatically, simply because exactly when it > is > safe to allow another thread to see the object and act on it is > higly specific to the application. But then why tinker to try and "fix" the deactivation of objects that have operations outstanding in them? This is just a special case of the same problem. Return-Path: Sender: "George Scott" Date: Wed, 15 Jul 1998 21:24:07 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Jonathan Biggar CC: port-rtf@omg.org Subject: Re: urgent POA issues References: <35AC23DC.7B2F1ECF@inprise.com> <35AD1E0D.5D3BF7C@floorboard.com> Jonathan Biggar wrote: > > George M. Scott wrote: > > > > > > 1408/1409 - problems with destroy(). The behavior of destroy is > not > > defined explicitly enough to guarantee consistency of programs. > > There was not consensus on 1428, 1408/1409 due to the requirement > that > the POA act as if it were in the discarding state. Many RTF members > want to find a solution that is more transparent to clients. OK, we have done more thinking on this and believe we can live with the holding state as I originally proposed more than a week ago. However, we would like to keep the escapes I describe in the proposal. That is, if there is no chance of the object being automatically reactivated or the POA being automatically recreated there is no need to hold, and OBJECT_NOT_EXIST can be returned immediately. This will help eliminate some deadlock situations. Also, it is possible for a client ORB to timeout a request if it has not received a reply for some period of time and issue a cancel request. In which case, deadlock would be avoided after some delay for the timeout. So if a vendor were to choose to provide such a feature in their product deadlock can be avoided. Also, we do consider the deadlock described to be a rare occurence and can be documented. > > - A new request arrives for A. The object is not in the active object map, > > so incarnate() is called on the ServantActivator. (Note, this does not > > violate the rules for serialization of ServantActivators which state that > > incarnation may not overlap for objects which were incarnated by a > > ServantActivator because the original object A was activated explicitly > > using activate_object.) Because A is still in the server and has not > > been etherealized, a "stale" version of A will be incarnated from the > > database, which we will call A'. Eventually the requests executing in > > A will complete and A will be etherealized to the database. When A' > > is etherealized it will overwrite A. The database is now most > > likely completely inconsistent. > > It would be better to explicitly modify the text to state that when the > POA uses a ServantActivator, that explicit calls to activate_object() > and deactivate_object() are also serialied in the same way as > incarnate() and etherealize() are. I prefer not to add any additional serialization to such calls as they introduce additional blocking which only adds more potential deadlock situations. > > > - Now consider what happens to requests that are executing in A > after > > A has been deactivated. If they call any POA operation which > requires > > the use of the active object map (i.e. the RETAIN policy), they > will > > get the incorrect result. For instance, if they call > id_to_servant > > they may get ObjectNotActive, however if the A' in the above > scenario > > has already been created they may get the Servant for A' which > will > > most likely be different than the Servant for A. The results > could > > be disastorous for the application. > > No A' should exist due to my above comment. It is questionable > whether > this is a pracital scenario. Since the request is operating in the > context of the servant already, why should the operation > implementation > need to call id_to_servant()? see my previous posting. > > > 4. Deadlocks should not occur. Now, I will be the first to admit > that this > > is nearly impossible to prove in a complex distributed system. > But I would > > like to eliminate the obvious ones. Our previous proposals > could deadlock > > because two objects in two different processes could have a > mutual > > recursion which could result in deadlock. For example object A > could call > > object B in another server, object B then attempts to call > object A again. > > However, right before object B calls object A another thread in > object > > A's server attempts to deactivate A or destroy A's POA. This > will result > > in deadlock because our previous proposal would act as if the > POA's > > POAManager was in the holding state which will queue requests > and hence > > block, resulting in deadlock. Our new proposal states that the > object > > will behave as if it is in the discarding state which means it > will not > > queue the request but instead throw the TRANSIENT exception. > > > > What a client ORB or application does with TRANSIENT is not > currently > > defined in any CORBA spec, but it does say the request should > be reissued. > > So an ORB may simply repeatedly reissue the request resulting > in a > > livelock, or it may be intelligent and realize that after five > minutes > > of receiving transients it may as well give up. > > True, it is not explicitly stated, but the weight of the evidence > suggests that an ORB is supposed to make the TRANSIENT exception > visible > to client code. Ok, since it turns out the TRANSIENT issue is a little harder for people to swallow than I expected. We will go back to the holding state as I disucssed above. > A more general question is whether this tightly coupled design (A calls > B which calls A) is desireable in the first place. I think most > designers would see this as a trouble spot right away, and redesign the > system to use an event channel or oneway call to resolve the deadlock. Yes, this is probably true. Again, as we have already discussed this is a rare deadlock situation and one I think we can live with. George Return-Path: Sender: "George Scott" Date: Wed, 15 Jul 1998 22:08:14 -0700 From: "George M. Scott" Organization: Inprise Corporation To: Paul H Kyzivat CC: port-rtf@omg.org Subject: Re: urgent POA issues References: <35AC23DC.7B2F1ECF@inprise.com> <35AD332B.F8D71F57@noblenet.com> Paul H Kyzivat wrote: > > George M. Scott wrote: > > > Imagine a server which represents millions of database records by > > encapsulating them in CORBA Objects. A servant activator is > installed > > to incarnate and etherealize the objects as necessary. The CORBA > > server essentially serves as a cache for the database. Objects are > > periodically deactivated to conserve memory which results in > > etherealize being called and their current state being written > back to > > the database. For improved startup time, a number of objects are > > pre-activated when the server is started by explicitly calling > > activate_object rather than wait for the ServantManager to create > > them. > > I presume you are assuming a UNIQUE_ID policy so that a given > servant is > associated with at most one object. Yes. > > > > - A new request arrives for A. The object is not in the active > > object map, > > so incarnate() is called on the ServantActivator. (Note, this > does > > not > > violate the rules for serialization of ServantActivators which > > state that > > incarnation may not overlap for objects which were incarnated > by a > > ServantActivator because the original object A was activated > > explicitly > > using activate_object.) Because A is still in the server and > has > > not > > been etherealized, a "stale" version of A will be incarnated > from > > the > > database, which we will call A'. Eventually the requests > executing > > in > > A will complete and A will be etherealized to the database. > When > > A' > > is etherealized it will overwrite A. The database is now most > > likely completely inconsistent. > > OK, I think I see your problem. The spec implied to me (although it > isn't explicit) that the serialization of incarnate and etherealize > must > extent to stalling a subsequent incarnation while an etherealization > is > pending for the same objectId. > > This is different than requiring the object to remain active until > the > etherealization begins - tests for the presence of the object can > still > fail (because it has been deactivated) and an explict activation is > OK. No, because a user can also call activate_object and not use incarnate and this will result in two copies of an object being created. > > > > > - Now consider what happens to requests that are executing in A > after > > A has been deactivated. If they call any POA operation which > > requires > > the use of the active object map (i.e. the RETAIN policy), they > > will > > get the incorrect result. For instance, if they call > id_to_servant > > they may get ObjectNotActive, however if the A' in the above > > scenario > > has already been created they may get the Servant for A' which > will > > most likely be different than the Servant for A. The results > could > > be disastorous for the application. > > Given the interpretation I gave above, there would be no A' while > there > are requests executing in A. No, because even outside of incarnate a user can call activate_object after deactivate_object and have multiple copies running. > It indeed might be the case that id_to_servant would fail. This has > nothing to do with the timing of etherealization - it only has to do > with explicit multithreading code written by the developer. Why > should > it succeed? It is unwise to be be writing code that depends on > activations in a POA while at the same time writing concurrent code > that > removes them. And this isn't a hard thing to avoid in this case > since > the servant ought to already know who it is, or it can find out from > POACurrent. Several members of the OMG are currently working on a proposal for CORBA components. As part of this proposal users will write components (servants) which implement some business logic or other functions. These components will be deployed in a container (POA + extra code) which will activate/deactivate objects as necessary. So the user will actually have little control over the concurrency of calls executing while an object is being deactivated because they are not writing the entire server, only a single servant which is running inside of a sophisticated component server. It is not safe to assume that a single person wrote all code which runs inside of a server process. > > There are many variations on the above scenarios which can all occur > > because the apparent deactivation of an object occured before it > > should have. With the current model users will have to always be > > prepared to handle this strange behavior in all user code. This will > > make development of CORBA components which can be dynamically managed > > in memory by intelligent application servers very difficult if not > > impossible. > > There are (at least) three things going on here: > - removal of the oid:servant association from the map > - etherealization of the oid:servant association > - deletion of the servant deletion of the servant is a language mapping issue which can be handled by garbage collection or proper reference counting. > No matter what we do, all of these need to be dealt with, > and these may all occur at (more-or-less) the same time, or > at widely spaced times, or not at all, in various combinations. > The existing policies make some combinations easier to use than > others. > > You are not going to get agreement about when these things "should" > occur because there is no one answer. > > You seem to think that one particular combination of interest to you > is > not currently supported (or at least isn't easily used), and are > also > proposing that another combination that is currently allowed is bad > or > useless and should be replaced by the one you want. There is only one combination and that is the one you have listed. It is only the timing I question. And I only question the timing if there are requests executing. The current spec already states that etherealization cannot occur until there are no requests executing, so the timing of etherealization and servant destruction are already fixed in the spec. So I'm trying to change the timing of only one element. A farily minor change and not as ominous as you make it sound. > These things should be separate considerations. If some feature is > without merit then we should perhaps consider removing it. If what > you > want is not currently possible AND is important then we should > consider > adding it. Yes, what I want is consistency, and it is not currently possible, so I would hope we would consider adding it. > > Users will have to modify their code to handle the > > incosistent behavior and such modification will most likely be > > dependent on the particular server in which a CORBA component is > being > > deployed. We may as well just give the market to Microsoft now, > and > > not waste our time. All dramatics aside, this is a serious > problem > > which > > needs to be addressed and very soon in my opinion. > > Inconsistency is yet another issue. I agree that we should be clear > about what the user can expect, and that this contract should be > sufficient for use. On the other hand, one of the most important > (and > hardest) things a standard must do is decide what does not need to > be > standardized. There must not be needless restrictions that prevent > ORB > implementors from making implementation decisions. It is perfectly > acceptable for a standard to say that some aspect of behavior is > explicitly undefined. Yes, but undefined behavior was previously spelled BOA. We are now trying to define behavior so programs can be written in a portable fashion. I agree there are certain things that can remain undefined and I don't think anything I have proposed is forcing any vendor to use a particular implementation. It is merely adding stronger semantics to the spec, which a vendor must implement, but there are still many possible implementations. > The problems come when some people think a behavior is defined and > others think it is not. Agreed. > > Now if it isn't clear already, the POA destroy operation has the exact > > same > > problem. If the server were to manage objects by destroying entire > > POAs > > instead of individual objects then it is possible to have a POA B and > > a POA > > B' in existence at the same time. And not only have a single object > > inconsistent but an entire set of objects managed by that POA totally > > inconsistent. I'm sure that will sell a lot of POA > > implementations.... > > The analogy isn't perfect. In the case of POAs, the only thing that is > ever explicitly visible is a reference to a POA - there are no visible > POA servants (though they may exist in a particular ORB implementation.) > > Just as a regular object reference remains invariant though it may map > to different servants from time to time, a reference to a POA should > also remain invariant though it may refer to a different incarnation of > that POA from time to time. So it should never appear as if there is > both a B and a B'. I'm confused by your statement. Are you saying that a reference to a POA that is destroyed and then is later recreated is still a valid reference? I don't think this is the case. And if it is the case, then this should be very explicitly stated in the spec. For example: Imagine the rootPOA is available and has an adapter activator installed which can create a POA named "foo". Executing the following code will activate the POA, then destroy it. // Java POA a = rootPOA.find_POA("foo", true); a.destroy(false, false); Now are you stating that if I now invoke an operation on "a", that it will recreate the POA? For example: a.the_name(); will actually reactivate the POA? Or will it throw OBJECT_NOT_EXIST. It was my understanding that a destroyed POA will always throw OBJECT_NOT_EXIST when invoked, and recreating the same POA will not result in the old reference suddenly becoming valid again. > > > But I would > > like to eliminate the obvious ones. Our previous proposals > could > > deadlock > > because two objects in two different processes could have a > mutual > > recursion which could result in deadlock. For example object A > > could call > > object B in another server, object B then attempts to call > object A > > again. > > However, right before object B calls object A another thread in > > object > > A's server attempts to deactivate A or destroy A's POA. This > will > > result > > in deadlock because our previous proposal would act as if the > POA's > > POAManager was in the holding state which will queue requests > and > > hence > > block, resulting in deadlock. Our new proposal states that the > > object > > will behave as if it is in the discarding state which means it > will > > not > > queue the request but instead throw the TRANSIENT exception. > > I don't think deadlocks of this sort are a big issue, because hardly > anyone is going to destroy POAs dynamically and to do so in > conjunction > with mutual recursion would be remarkable. > > That said, I would rather risk the deadlock than throw away the > requests. If somebody wants this kind of behavior they can first set > the > POAs POAManager to discarding and then destroy the POA. Yes, I think we all agree this is probably a rare case. Though, I know one day some end user of CORBA will hit this problem and we'll hear about it. > > What a client ORB or application does with TRANSIENT is not > > currently > > defined in any CORBA spec, but it does say the request should > be > > reissued. > > So an ORB may simply repeatedly reissue the request resulting > in a > > livelock, or it may be intelligent and realize that after five > > minutes > > of receiving transients it may as well give up. This is > > I don't think the spec mandates that an ORB should automatically > retry a > request when a transient exception is received. I don't even think > it is > a good idea. Unless or until it is clear that this is required > behavior > we should assume that an ORB client is going to get the exception > and > have to deal with it explicitly - it is going to bother somebody. Yes, I have received quite a bit of feedback on what people think TRANSIENT means, so I'm going to propose using the holding state instead. George Return-Path: Sender: jon@floorboard.com Date: Wed, 15 Jul 1998 22:52:04 -0700 From: Jonathan Biggar To: "George M. Scott" CC: Paul H Kyzivat , port-rtf@omg.org Subject: Re: urgent POA issues References: <35AC23DC.7B2F1ECF@inprise.com> <35AD332B.F8D71F57@noblenet.com> <35AD8ABE.D8982CAB@inprise.com> George M. Scott wrote: > I'm confused by your statement. Are you saying that a reference to a > POA that is destroyed and then is later recreated is still a valid > reference? I don't think this is the case. And if it is the case, then > this should be very explicitly stated in the spec. For example: > > Imagine the rootPOA is available and has an adapter activator installed > which can create a POA named "foo". Executing the following code will > activate the POA, then destroy it. > > // Java > POA a = rootPOA.find_POA("foo", true); > a.destroy(false, false); > > Now are you stating that if I now invoke an operation on "a", that it > will recreate the POA? For example: > > a.the_name(); > > will actually reactivate the POA? Or will it throw OBJECT_NOT_EXIST. > It was my understanding that a destroyed POA will always throw > OBJECT_NOT_EXIST when invoked, and recreating the same POA will not > result in the old reference suddenly becoming valid again. I agree with George. A reference to a POA that is destroyed should never work again, even when a POA with the same name is recreated. Practically, if the ORB implements POAs as objects mediated by the root POA, which has the TRANSIENT and SYSTEM_ID policies, this is the case anyway. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Fri, 17 Jul 1998 13:38:08 +1000 (EST) From: Michi Henning To: Paul H Kyzivat cc: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() Content-ID: On Thu, 16 Jul 1998, Paul H Kyzivat wrote: > > I don't think any amount of tinkering with the POA can ever to this > > work > > for the server writer automatically, simply because exactly when it is > > safe to allow another thread to see the object and act on it is > > higly specific to the application. > > But then why tinker to try and "fix" the deactivation of objects that > have operations outstanding in them? This is just a special case of the > same problem. No, I don't think so. Object life cycle is "special", because only the application can know when an object has been completely created, and is therefore available to other threads. Similarly, only the application can know where all the bits of state (which may be in multiple places) for an object are and therefore must coordinate access to the object during its destruction. The issue with deactivation of objects that have operations outstanding on them is not a special case, because it arises for all operations, not just life cycle operations. In particular, if there is no way for an application to know when all threads have left an object, there is no way for the app to ever destroy the object safely. So, the ORB has to help with that. But at least to me, that doesn't mean that the ORB has to do all the work of locking and provide a completely transparent solution. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html x Return-Path: Date: Mon, 20 Jul 1998 11:07:37 -0400 From: Paul H Kyzivat Organization: NobleNet To: "George M. Scott" CC: port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> George M. Scott wrote: > Again, the proposal is not addressing the issue of memory management > this is a completely orthogonal issue. I keep phrasing things this way because I don't know how else to understand what your issue is. > > > The other case (I guess the one that bothers you) is > > servant_to_reference. As far as I am concerned, if a server > activates an > > object with a servant, then deactivates it, it should not expect > > servant_to_reference to return a reference to the now-deactivated > > object. However there has been a proposal that > servant_to_reference > > should always take into account the servant for the current > invocation > > context (if any) and in that case use the id from the invocation > context > > to construct the reference. I could live with that. > > It's not just servant_to_reference, it is all of the *_to_* > conversions > which use the active object map where * is one of servant, > reference, > or id. You can make all of these context sensitive, but it is not > necessary if you simply enfore the simple rule which is an object > may > not be removed from the map when requests are active. Once the > object > it is out of the map, it may be recreated and there will be two > instances of the same object living in the POA and this is not a > good > thing. You speak of removing an object from the map... can you please explain precisely what you mean by object? The way I think of it, a corba object is whatever a corba object reference refers to. If the object is served by a server using the POA spec, then this effectively means an objectId within a particular named POA. This has nothing to do with whether the ObjectId is present in the map, or even if there is a map. You seem to be concerned with a particular pairing of an ObjectId and a Servant. In some cases such a pairing may be considered to be "the" object for some period of time, but there are also cases when this is not so. For instance, when using a servant locator, there can be multiple concurrent pairings of the same ObjectId to different servants. I keep coming back to focus on the servant and its lifetime because often it is the servant that captures the dynamic state of "the" object. When it does, and when a servant activator is in use, it is etherealization that provides the opportunity to persist the state. We have now concluded that reference counting is needed to fully and correctly manage servant lifetime in some cases. When reference counting is used with servants that cache state, I think the persisting of that state will have to be done by the object's destructor. This is why these issues cannot be decoupled. > > > > The proposal is simply stating that an object cannot be > deactivated > > > while > > > it is in use. So if it is in use, then it will still appear to > be > in > > > the > > > active object map, regardless if a call to the POA was made from > the > > > context of that object or not. This is completely consistent > > > behavior. > > > All threads will see the same behavior whether or not they are > in > a > > > calling context. When there are no active requests they will > see > the > > > object removed. There are no inconsistencies. > > > > You and I seem to have different notions of what it means for an > object > > to be "in use". I gather you consider it to be in use only when it > has > > been selected as the target of an in-progress invocation. > > Correct. > > > I consider this to just be a special case of some piece of server > code > > manipulating an oid or servant for what it believes to be an > activated > > object. In particular the example above of server code calling > > id_to_servant puts that object into use just as surely as does an > > invocation on the object. > > > > But your proposal does not deal with this other kind of use. > > > > For a concrete example: > > > > Suppose we have a factory object that creates and returns > references > to > > other objects, like CosNaming::NamingContext::new_context to be > > specific. Perhaps the implementation of new_context decides to do > > something like the following (crude pseudo-code): > > > > ctx_servant = new ContextImpl(); > > poa->activate_object(ctx_servant); > > // 1 > > return ctx_servant->_this(); > > > > At point 1 it is possible that another thread in the server > decides > to > > deactivate this object. If there is a servant activator, > etherealize > > will be called, and since there are no invocations of this object > in > > progress it may well decide to delete the servant. Then the call > to > > _this will crash in flames. The proposal doesn't fix this because > it > > doesn't consider the object to be "in use" here. > > Again, you are confusing the memory management issue with my > proposal. > In my proposal, when you call _this() it would throw an exception > because the object is no longer active, not core dump. For example, > in Java you still have a reference to the object so it cannot be > garbage collected. If reference counting were properly implemented > for Servants in the c++ mapping of the POA, then your servant would > presumably have a ref of 1 even after _this() was called, and would > not be deleted until you unrefed it. How is it that in your proposal the servant pointer would be valid in order to return an exception? By your definition of "in use" this object is not in use, so etherealization and destruction of the servant could occur at point 1. > > > My first reaction to this was to consider that the java mapping > might be > > broken. I don't think we are obligated to fix the POA spec to deal > with > > that. > > No, but then the Java mapping would be obligated to add a speical > POA > operation for the Java mapping only to solve this problem. > > > The change proposed by someone to make servant_to_reference > consider > the > > current invocation context would solve this problem. > > > > A change to POACurrent to provide access to the servant would also > allow > > you to implement _this() to handle this case. > > > > Either of these would be preferable (in my opinion) to the > proposal > we > > are discussing. > > These still do not prevent multiple copies of the same object from > running at the same time. Again, could you explain what you mean by "multiple copies of the same object ... at the same time"? This is exactly what happens with a servant locator, so there is nothing intrinsicly wrong with having two servants concurrently servicing distinct requests for the same ObjectId. It is only wrong if they each think they are alone. This problem can only occur if the server explicitly activates objects and then uses a servant activator to clean up after them. If it does this then it should be aware of the problem. If it uses incarnate to activate the objects then there is no problem. Return-Path: Date: Mon, 20 Jul 1998 11:40:12 -0400 From: Paul H Kyzivat Organization: NobleNet To: "George M. Scott" CC: Jonathan Biggar , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> <35A39D6F.879ACFE4@noblenet.com> <35A3A2D6.B0277A5B@floorboard.com> <35AD1841.37EF0352@noblenet.com> <35AD7CB3.1AD669C4@inprise.com> George M. Scott wrote: > > Paul H Kyzivat wrote: [snip] > > I agree with you on this - but apparently not on what a necessary > and > > sufficient fix is. Keeping the id/servant in the map until the > operation > > returns isn't going to solve this problem. > > > > In general there is no solution that doesn't potentially involve a > wait > > or a (possibly delayed) call to etherealize, or reference > counting. > > Waiting and etherealization are already available. I don't believe > we > > need new ways to wait. Reference counting is all that is left. > > I hate to keep repeating myself. But the proposal is not attempting > to > solve the memory management problem. The solution for that requires > a change to the C++ language mapping, not the POA. This isn't just a memory management issue. Until the reference count goes to zero it is not safe for the servant to save its state persistently. (Someone holding a reference to the servant may call it and cause its state to change.) I now see that this may lead to an even more difficult variation on the problem you are concerned with: Suppose one thread holds a pointer to a reference counted servant that is also activated in some POA. Another thread deactivates it. There are no outstanding operations on the object, so etherealize is called and does a remove_ref on the servant. (The servant doesn't go away because of the other thread reference.) Now an incoming request for the object causes incarnate to be called. This now creates a new servant and initializes it from persistent state, records the new servant in the active object map, and dispatches the incoming request. Finally, the other thread does a remove_ref on the old servant; it then updates persistent state, according to the values it contains. I must say that I don't at the moment see how to fix this problem. It looks like etherealize can never be relied upon to be correct if the servant can be referenced outside of an invocation. Return-Path: Sender: jon@floorboard.com Date: Mon, 20 Jul 1998 09:02:28 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> <35B35D39.7E617C57@noblenet.com> Paul H Kyzivat wrote: > > It's not just servant_to_reference, it is all of the *_to_* > > conversions > > which use the active object map where * is one of servant, > reference, > > or id. You can make all of these context sensitive, but it is not > > necessary if you simply enfore the simple rule which is an object > may > > not be removed from the map when requests are active. Once the > object > > it is out of the map, it may be recreated and there will be two > > instances of the same object living in the POA and this is not a > good > > thing. > > You speak of removing an object from the map... can you please > explain > precisely what you mean by object? The particular case he is talking about here is a POA with RETAIN and USE_SERVANT_MANAGER. > The way I think of it, a corba object is whatever a corba object > reference refers to. If the object is served by a server using the > POA > spec, then this effectively means an objectId within a particular > named > POA. This has nothing to do with whether the ObjectId is present in > the > map, or even if there is a map. Don't get carried away with the terminology here. The case under discussion is the issue of handling the active object map, which only applies to a POA using the RETAIN policy. The other stuff you mention here is out of bounds of the discussion. > I keep coming back to focus on the servant and its lifetime because > often it is the servant that captures the dynamic state of "the" > object. > When it does, and when a servant activator is in use, it is > etherealization that provides the opportunity to persist the > state. We > have now concluded that reference counting is needed to fully and > correctly manage servant lifetime in some cases. When reference > counting > is used with servants that cache state, I think the persisting of > that > state will have to be done by the object's destructor. This is why > these > issues cannot be decoupled. No. The POA spec is explicitly designed for stateful servants to persist their state during the etherealization process, and no one is proposing anything different. Reference counting servants is only needed for C and C++ (and maybe Ada), not all language mappings, and only to handle the explicit need for the programmer to know when it is safe to free the memory used by the servant. The lifetime of the memory associated with the servant is a different issue than the question of when a servant should save its state to persistent storage. > > > For a concrete example: > > > > > > Suppose we have a factory object that creates and returns > references > > to > > > other objects, like CosNaming::NamingContext::new_context to be > > > specific. Perhaps the implementation of new_context decides to > do > > > something like the following (crude pseudo-code): > > > > > > ctx_servant = new ContextImpl(); > > > poa->activate_object(ctx_servant); > > > // 1 > > > return ctx_servant->_this(); > > > > > > At point 1 it is possible that another thread in the server > decides > > to > > > deactivate this object. If there is a servant activator, > etherealize > > > will be called, and since there are no invocations of this > object in > > > progress it may well decide to delete the servant. Then the call > to > > > _this will crash in flames. The proposal doesn't fix this > because it > > > doesn't consider the object to be "in use" here. > > > > Again, you are confusing the memory management issue with my > proposal. > > In my proposal, when you call _this() it would throw an exception > > because the object is no longer active, not core dump. For > example, > > in Java you still have a reference to the object so it cannot be > > garbage collected. If reference counting were properly > implemented > > for Servants in the c++ mapping of the POA, then your servant > would > > presumably have a ref of 1 even after _this() was called, and > would > > not be deleted until you unrefed it. > > How is it that in your proposal the servant pointer would be valid > in > order to return an exception? By your definition of "in use" this > object > is not in use, so etherealization and destruction of the servant > could > occur at point 1. Not when coupled with the proposal to add reference counting to the C++ language mapping. In his proposal, the POA would increment the ref count again when activate_object() is called, and the user could would retain a reference to the servant. This would prevent destruction of the servant at point 1, although etherealization could have occured already. But that isn't a problem, since calling _this() will just reactivate the object. (Since he is using activate_object(), his POA must have the IMPLICIT_ACTIVATION policy, so using _this() to reactivate the object is ok.) > > These still do not prevent multiple copies of the same object from > > running at the same time. > > Again, could you explain what you mean by "multiple copies of the > same > object ... at the same time"? This is exactly what happens with a > servant locator, so there is nothing intrinsicly wrong with having > two > servants concurrently servicing distinct requests for the same > ObjectId. > > It is only wrong if they each think they are alone. This problem can > only occur if the server explicitly activates objects and then uses > a > servant activator to clean up after them. If it does this then it > should > be aware of the problem. If it uses incarnate to activate the > objects > then there is no problem. I think you guys are getting stuck on the "multiple active copies" issue, which is really peripheral to the problem at hand. So lets ignore the memory management of servants for now (let's pretend we are talking about Java, where the issue does not exist). The question on the table is whether and explicit call to deactivate_object() should delay removing the OID from the active object map until all outstanding requests have been completed. The second question is whether deactivate_object() should block until this is done. Frankly, as long as we fix the problem with servant_to_reference() to allow the Java mapping to define _this() to use servant_to_reference() (to provide for their binary portability layer), I don't think the answer to either question needs to be yes. Since a request is operating in the context of a servant already, and since the OID is available via Current, I don't really see much practical need for the request to access the information in the activate object map entry anyway. But even so, etherealization clearly must wait until the requests are done, because the spec says so, and because it is obvious that the state of the servant can't be flushed to persistent storage until the requests are done fiddling with it. As far as the "multiple active copies" problem goes, I still believe that the POA spec needs text to clarify that activate_object() and deactivate_object() are properly serialized with respect to incarnate() and etherealize() to prevent multiple servants being active for the same OID. Without this, the POA spec is broken, pure and simple. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: jon@floorboard.com Date: Mon, 20 Jul 1998 09:11:32 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> <35A39D6F.879ACFE4@noblenet.com> <35A3A2D6.B0277A5B@floorboard.com> <35AD1841.37EF0352@noblenet.com> <35AD7CB3.1AD669C4@inprise.com> <35B364DC.2D1D5DD7@noblenet.com> Paul H Kyzivat wrote: > > George M. Scott wrote: > > > > Paul H Kyzivat wrote: > [snip] > > > I agree with you on this - but apparently not on what a > necessary > > and > > > sufficient fix is. Keeping the id/servant in the map until the > > operation > > > returns isn't going to solve this problem. > > > > > > In general there is no solution that doesn't potentially involve > a > > wait > > > or a (possibly delayed) call to etherealize, or reference > counting. > > > Waiting and etherealization are already available. I don't > believe > > we > > > need new ways to wait. Reference counting is all that is left. > > > > I hate to keep repeating myself. But the proposal is not > attempting > > to > > solve the memory management problem. The solution for that > requires > > a change to the C++ language mapping, not the POA. > > This isn't just a memory management issue. > > Until the reference count goes to zero it is not safe for the > servant to > save its state persistently. (Someone holding a reference to the > servant > may call it and cause its state to change.) No Paul, it is clear to everyone else that etherealization is the point for the servant to save its state. If the POA is not using a servant manager, then the point just before where deactivate_object() is called would also be a good point to save the state of the servant. It's not hard for the programmer to make sure that operations on the servant know whether the state is in memory or in the persistent store. All it takes is an extra bit in the servant. > I now see that this may lead to an even more difficult variation on the > problem you are concerned with: > > Suppose one thread holds a pointer to a reference counted servant that > is also activated in some POA. Another thread deactivates it. There are > no outstanding operations on the object, so etherealize is called and > does a remove_ref on the servant. (The servant doesn't go away because > of the other thread reference.) At this point, the etherealize should save the servant's persistent state. Trying to delay this causes the problem you are afraid of here. > Now an incoming request for the object > causes incarnate to be called. This now creates a new servant and > initializes it from persistent state, records the new servant in the > active object map, and dispatches the incoming request. Finally, the > other thread does a remove_ref on the old servant; it then updates > persistent state, according to the values it contains. Nope, too late. This is why the persistent state must be saved at the point of etherealization (or explicit call to deactivate_object() if no servant manager is used), instead of at destruction time. > I must say that I don't at the moment see how to fix this problem. > It looks like etherealize can never be relied upon to be correct if > the > servant can be referenced outside of an invocation. The purpose of the reference counting is to allow the programmer a safe point to destroy the servant's memory, not to allow access to the servant's persistent state after etherealization is called. Any program that attempts to access the servant's persistent state after etherealization is simply erroneous. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Mon, 20 Jul 1998 18:51:57 -0400 From: Paul H Kyzivat Organization: NobleNet To: Jonathan Biggar CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> <35B35D39.7E617C57@noblenet.com> <35B36A14.5C0EF312@floorboard.com> Jonathan Biggar wrote: > > I keep coming back to focus on the servant and its lifetime > because > > often it is the servant that captures the dynamic state of "the" > object. > > When it does, and when a servant activator is in use, it is > > etherealization that provides the opportunity to persist the > state. > We > > have now concluded that reference counting is needed to fully and > > correctly manage servant lifetime in some cases. When reference > counting > > is used with servants that cache state, I think the persisting of > that > > state will have to be done by the object's destructor. This is why > these > > issues cannot be decoupled. > > No. The POA spec is explicitly designed for stateful servants to > persist their state during the etherealization process, and no one > is > proposing anything different. Reference counting servants is only > needed for C and C++ (and maybe Ada), not all language mappings, and > only to handle the explicit need for the programmer to know when it > is > safe to free the memory used by the servant. The lifetime of the > memory > associated with the servant is a different issue than the question > of > when a servant should save its state to persistent storage. I certainly agree that the POA appears to have been designed with this intent in mind. It also appears to have been designed to allow the creation and destruction of the servant to be handled by the servant manager. It now seems that this latter goal was not met. It seems to me that the former is similarly not met, given reasonable assumptions. > > > > > For a concrete example: > > > > > > > > Suppose we have a factory object that creates and returns > references > > > to > > > > other objects, like CosNaming::NamingContext::new_context to > be > > > > specific. Perhaps the implementation of new_context decides to > do > > > > something like the following (crude pseudo-code): > > > > > > > > ctx_servant = new ContextImpl(); > > > > poa->activate_object(ctx_servant); > > > > // 1 > > > > return ctx_servant->_this(); > > > > > > > > At point 1 it is possible that another thread in the server > decides > > > to > > > > deactivate this object. If there is a servant activator, > etherealize > > > > will be called, and since there are no invocations of this > object in > > > > progress it may well decide to delete the servant. Then the > call > to > > > > _this will crash in flames. The proposal doesn't fix this > because it > > > > doesn't consider the object to be "in use" here. > > > > > > Again, you are confusing the memory management issue with my > proposal. > > > In my proposal, when you call _this() it would throw an > exception > > > because the object is no longer active, not core dump. For > example, > > > in Java you still have a reference to the object so it cannot be > > > garbage collected. If reference counting were properly > implemented > > > for Servants in the c++ mapping of the POA, then your servant > would > > > presumably have a ref of 1 even after _this() was called, and > would > > > not be deleted until you unrefed it. > > > > How is it that in your proposal the servant pointer would be valid > in > > order to return an exception? By your definition of "in use" this > object > > is not in use, so etherealization and destruction of the servant > could > > occur at point 1. > > Not when coupled with the proposal to add reference counting to the > C++ > language mapping. In his proposal, the POA would increment the ref > count again when activate_object() is called, and the user could > would > retain a reference to the servant. This would prevent destruction > of > the servant at point 1, although etherealization could have occured > already. But that isn't a problem, since calling _this() will just > reactivate the object. (Since he is using activate_object(), his > POA > must have the IMPLICIT_ACTIVATION policy, so using _this() to > reactivate > the object is ok.) I admit to being wrong here - it is possible to write the code in a safe way under the new reference counting proposal: ctx_servant = new ContextImpl(); poa->activate_object(ctx_servant); // 1 CosNaming::NamingContext_var ctx = ctx_servant->_this(); ctx_servant->_remove_ref(); return ctx._retn(); Not especially appealing if you ask me, but I think it will work. (With the proposed change to reference counting that I just posted you can remove two lines from this, back to my original example and still have it be correct.) > I think you guys are getting stuck on the "multiple active copies" > issue, which is really peripheral to the problem at hand. So lets > ignore the memory management of servants for now (let's pretend we > are > talking about Java, where the issue does not exist). The question > on > the table is whether and explicit call to deactivate_object() should > delay removing the OID from the active object map until all > outstanding > requests have been completed. The second question is whether > deactivate_object() should block until this is done. > > Frankly, as long as we fix the problem with servant_to_reference() > to > allow the Java mapping to define _this() to use > servant_to_reference() > (to provide for their binary portability layer), I don't think the > answer to either question needs to be yes. Since a request is > operating > in the context of a servant already, and since the OID is available > via > Current, I don't really see much practical need for the request to > access the information in the activate object map entry anyway. But > even so, etherealization clearly must wait until the requests are > done, > because the spec says so, and because it is obvious that the state > of > the servant can't be flushed to persistent storage until the > requests > are done fiddling with it. I can agree with everything you have written here. > v> As far as the "multiple active copies" problem goes, I still believe > that the POA spec needs text to clarify that activate_object() and > deactivate_object() are properly serialized with respect to > incarnate() > and etherealize() to prevent multiple servants being active for the > same > OID. Without this, the POA spec is broken, pure and simple. I can agree with this, depending on the mechanism. I agree with George (I think it was him) that turning activate_object into a blocking operation is a bad thing to do. How about throwing an exception (BAD_INV_ORDER?) if there is an attempt to activate an object while an incarnation or etherealization of the same ObjectId is pending? This seems like a design error so I have no problem with it being an exception. Return-Path: Sender: jon@floorboard.com Date: Mon, 20 Jul 1998 15:55:30 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> <35B35D39.7E617C57@noblenet.com> <35B36A14.5C0EF312@floorboard.com> <35B3CA0D.C79B5A13@noblenet.com> Paul H Kyzivat wrote: > > As far as the "multiple active copies" problem goes, I still > believe > > that the POA spec needs text to clarify that activate_object() and > > deactivate_object() are properly serialized with respect to > > incarnate() > > and etherealize() to prevent multiple servants being active for > the > > same > > OID. Without this, the POA spec is broken, pure and simple. > > I can agree with this, depending on the mechanism. I agree with > George > (I think it was him) that turning activate_object into a blocking > operation is a bad thing to do. > > How about throwing an exception (BAD_INV_ORDER?) if there is an > attempt > to activate an object while an incarnation or etherealization of the > same ObjectId is pending? This seems like a design error so I have > no > problem with it being an exception. No, I disagree. I think it is quite reasonable to explicitly activate and object even when a ServantActivator is being used by the POA, and in fact necessary under many circumstances. Consider the following scenario: Our POA has RETAIN, USE_SERVANT_MANAGER, PERSISTENT. When a request comes in for an inactive object the object is incarnated by the ServantActivator. Now consider if the object needs the state of another object managed by the same POA that is not active yet (maybe we are implementing a collection, or the Relationship service). How else do we code this, but by constructing a servant for the second object and explicitly calling activate_object()? Certainly the code that explicitly calls activate_object() do proper interlocking with the ServantActivator implementation to prevent having the servant created twice with the same state, but it appears to me that this is a quite reasonable thing to do, and in fact will be necessary quite often. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Mon, 20 Jul 1998 19:09:27 -0400 From: Paul H Kyzivat Organization: NobleNet To: Jonathan Biggar CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35A38DBD.A9D97B84@floorboard.com> <35A39D6F.879ACFE4@noblenet.com> <35A3A2D6.B0277A5B@floorboard.com> <35AD1841.37EF0352@noblenet.com> <35AD7CB3.1AD669C4@inprise.com> <35B364DC.2D1D5DD7@noblenet.com> <35B36C34.CEA3E767@floorboard.com> Jonathan Biggar wrote: > > Paul H Kyzivat wrote: > > Until the reference count goes to zero it is not safe for the > servant to > > save its state persistently. (Someone holding a reference to the > servant > > may call it and cause its state to change.) > > No Paul, it is clear to everyone else that etherealization is the > point > for the servant to save its state. If the POA is not using a > servant > manager, then the point just before where deactivate_object() is > called > would also be a good point to save the state of the servant. It's > not > hard for the programmer to make sure that operations on the servant > know > whether the state is in memory or in the persistent store. All it > takes > is an extra bit in the servant. Perhaps it is not hard in that sense, but it eliminates much of the value of having a servant activator. I always considered that the point of this was so that the individual methods need not consider persistence - this could be left entirely to incarnation and etherealization. If each method must check if its cached copy is up-to-date then a default servant does the job just fine. Suppose one thread fetches the servant for an activated object that is subsequently deactivated, etherealized, incarnated and updated in another thread. Then suppose the first thread then makes some local call on the servant that accesses its state. Even if the servant realizes its state is invalid, what is it to do? The correct state now lives in some other servant and has not yet been persisted. I agree we can keep the status quo, but it means that _remove_ref is just about the only valid thing you can do with a pointer to a servant that is (or was once) activated. This should get documented (in the spec or perhaps in some tutuorial book) because everybody is going to get it wrong. > > > I now see that this may lead to an even more difficult variation > on > the > > problem you are concerned with: > > > > Suppose one thread holds a pointer to a reference counted servant > that > > is also activated in some POA. Another thread deactivates > it. There > are > > no outstanding operations on the object, so etherealize is called > and > > does a remove_ref on the servant. (The servant doesn't go away > because > > of the other thread reference.) > > At this point, the etherealize should save the servant's persistent > state. Trying to delay this causes the problem you are afraid of > here. > > > Now an incoming request for the object > > causes incarnate to be called. This now creates a new servant and > > initializes it from persistent state, records the new servant in > the > > active object map, and dispatches the incoming request. Finally, > the > > other thread does a remove_ref on the old servant; it then updates > > persistent state, according to the values it contains. > > Nope, too late. This is why the persistent state must be saved at > the > point of etherealization (or explicit call to deactivate_object() if > no > servant manager is used), instead of at destruction time. Yes, your way fixes this problem, but not the problem I posed just above. Return-Path: Date: Mon, 20 Jul 1998 19:59:56 -0400 From: Paul H Kyzivat Organization: NobleNet To: Jonathan Biggar CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> <35B35D39.7E617C57@noblenet.com> <35B36A14.5C0EF312@floorboard.com> <35B3CA0D.C79B5A13@noblenet.com> <35B3CAE2.C7A78813@floorboard.com> Jonathan Biggar wrote: > > Paul H Kyzivat wrote: > > > As far as the "multiple active copies" problem goes, I still > believe > > > that the POA spec needs text to clarify that activate_object() > and > > > deactivate_object() are properly serialized with respect to > > > incarnate() > > > and etherealize() to prevent multiple servants being active for > the > > > same > > > OID. Without this, the POA spec is broken, pure and simple. > > > > I can agree with this, depending on the mechanism. I agree with > George > > (I think it was him) that turning activate_object into a blocking > > operation is a bad thing to do. > > > > How about throwing an exception (BAD_INV_ORDER?) if there is an > attempt > > to activate an object while an incarnation or etherealization of > the > > same ObjectId is pending? This seems like a design error so I have > no > > problem with it being an exception. > > No, I disagree. I think it is quite reasonable to explicitly > activate > and object even when a ServantActivator is being used by the POA, > and > in > fact necessary under many circumstances. Consider the following > scenario: > > Our POA has RETAIN, USE_SERVANT_MANAGER, PERSISTENT. When a request > comes in for an inactive object the object is incarnated by the > ServantActivator. Now consider if the object needs the state of > another > object managed by the same POA that is not active yet (maybe we are > implementing a collection, or the Relationship service). How else > do > we > code this, but by constructing a servant for the second object and > explicitly calling activate_object()? > > Certainly the code that explicitly calls activate_object() do proper > interlocking with the ServantActivator implementation to prevent > having > the servant created twice with the same state, but it appears to me > that > this is a quite reasonable thing to do, and in fact will be > necessary > quite often. I wasn't suggesting that this necessarily be illegal. I see three distinct timing possibilities: 1) There are no attempted invocations on the object in question until after your explicit activation is complete. Everything should go as you wish - no errors. 2) After you decide you need to activate your object, a request arrives for the object. Incarnate is called and completes after you have created and initialized the servant, but before you have called activate_object. In this case, the call to activate_object will fail because of a duplicate ObjectId. 3) After you decide you need to activate your object, a request arrives for the object. An incarnate is pending but not yet complete at the time you call activate_object. This is the only new case, and is the one where I am proposing to throw some exception. What else can be done in this third case? As the spec is currently written, I believe the activate_object can succeed but then, when incarnate returns and the POA tries add it to the map there will be some sort of error. Not clear how that error is to be handled. If you were to block the activate_object call until the incarnation completed, it would fall over to case (2) and the activate_object would still fail. -- You didn't ask, but I would say that the correct way for you to handle this case would be by performing a colocated call on an object reference for the object you need state from. This will drive it through the servant manager and avoid all the race conditions. Return-Path: Sender: jon@floorboard.com Date: Mon, 20 Jul 1998 17:13:25 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> <35B35D39.7E617C57@noblenet.com> <35B36A14.5C0EF312@floorboard.com> <35B3CA0D.C79B5A13@noblenet.com> <35B3CAE2.C7A78813@floorboard.com> <35B3D9FC.E5C5B489@noblenet.com> Paul H Kyzivat wrote: > I wasn't suggesting that this necessarily be illegal. I see three > distinct timing possibilities: > > 1) There are no attempted invocations on the object in question > until > after your explicit activation is complete. Everything should go as > you > wish - no errors. > > 2) After you decide you need to activate your object, a request > arrives > for the object. Incarnate is called and completes after you have > created > and initialized the servant, but before you have called > activate_object. > In this case, the call to activate_object will fail because of a > duplicate ObjectId. > > 3) After you decide you need to activate your object, a request > arrives > for the object. An incarnate is pending but not yet complete at the > time > you call activate_object. This is the only new case, and is the one > where I am proposing to throw some exception. > > What else can be done in this third case? As the spec is currently > written, I believe the activate_object can succeed but then, when > incarnate returns and the POA tries add it to the map there will be > some > sort of error. Not clear how that error is to be handled. If you > were to > block the activate_object call until the incarnation completed, it > would > fall over to case (2) and the activate_object would still fail. Ok, now you have a real issue here. I could at least one way to fix cases 2 & 3. Simply allow activate_object() to succeed without error if the servant supplied is already the servant in the active object map. Also, simply allow the incarnate() to proceed without error if the servant it returns is already the one in the active object map. This would allow the programmer to arrange for code that calls activate_object() and the implementation of incarnate() to conspire to guarantee that there is only one servant created for each OID. Of course to do this would require that the programmer keep a parallel data structure to map OIDs to servants besides the active object map, but hey, you can't have everything! :-) > You didn't ask, but I would say that the correct way for you to handle > this case would be by performing a colocated call on an object reference > for the object you need state from. This will drive it through the > servant manager and avoid all the race conditions. This doesn't work if you need to access the servant through an interface that is not defined via IDL, and there certainly is plenty of need for that, even in the existing IDL services. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Tue, 21 Jul 1998 20:14:32 -0400 From: Paul H Kyzivat Organization: NobleNet To: Jonathan Biggar CC: "George M. Scott" , port-rtf@omg.org Subject: Re: Problems with deactivate_object() References: <359B0D17.4472DE6E@inprise.com> <35A11D1D.77E5953B@noblenet.com> <35AACA12.70084AEB@inprise.com> <35AB5CFF.2C52ED4@noblenet.com> <35ABF029.D82BFEAE@inprise.com> <35AD152B.986C8CA0@noblenet.com> <35AD78FC.85912E14@inprise.com> <35B35D39.7E617C57@noblenet.com> <35B36A14.5C0EF312@floorboard.com> <35B3CA0D.C79B5A13@noblenet.com> <35B3CAE2.C7A78813@floorboard.com> <35B3D9FC.E5C5B489@noblenet.com> <35B3DD25.75C36823@floorboard.com> Jonathan Biggar wrote: > > Paul H Kyzivat wrote: > > I wasn't suggesting that this necessarily be illegal. I see three > > distinct timing possibilities: > > > > 1) There are no attempted invocations on the object in question > until > > after your explicit activation is complete. Everything should go > as > you > > wish - no errors. > > > > 2) After you decide you need to activate your object, a request > arrives > > for the object. Incarnate is called and completes after you have > created > > and initialized the servant, but before you have called > activate_object. > > In this case, the call to activate_object will fail because of a > > duplicate ObjectId. > > > > 3) After you decide you need to activate your object, a request > arrives > > for the object. An incarnate is pending but not yet complete at > the > time > > you call activate_object. This is the only new case, and is the > one > > where I am proposing to throw some exception. > > > > What else can be done in this third case? As the spec is currently > > written, I believe the activate_object can succeed but then, when > > incarnate returns and the POA tries add it to the map there will > be > some > > sort of error. Not clear how that error is to be handled. If you > were to > > block the activate_object call until the incarnation completed, it > would > > fall over to case (2) and the activate_object would still fail. > > Ok, now you have a real issue here. Thank you! Finally somebody understands a point I am trying to make! > I could at least one way to fix > cases 2 & 3. Simply allow activate_object() to succeed without > error > if > the servant supplied is already the servant in the active object > map. > Also, simply allow the incarnate() to proceed without error if the > servant it returns is already the one in the active object map. > > This would allow the programmer to arrange for code that calls > activate_object() and the implementation of incarnate() to conspire > to > guarantee that there is only one servant created for each OID. Of > course to do this would require that the programmer keep a parallel > data > structure to map OIDs to servants besides the active object map, but > hey, you can't have everything! :-) And I proposed a different solution: throw an exception in response to activate_object if an incarnation or etherealization is *pending*. The timing of incarnation or etherealization is unpredictable anyway, this just makes activate_object receive the same result it would if the incarnation had already completed or the etherealization hadn't been requested yet. Aside from introducing some new special cases into the documented user interface to the POA, your solution doesn't work if the servants aren't the same. This is especially a problem if the incarnate happens last. It can't return an error to the incarnate routine because the problem is detected after it returns. And it seems silly to return the error to the operation that initiated incarnation because it didn't do anything wrong and now has everything it needs to continue. > > > You didn't ask, but I would say that the correct way for you to > handle > > this case would be by performing a colocated call on an object > reference > > for the object you need state from. This will drive it through the > > servant manager and avoid all the race conditions. > > This doesn't work if you need to access the servant through an > interface > that is not defined via IDL, and there certainly is plenty of need > for > that, even in the existing IDL services. I was waiting for someone to suggest this :) In one of my replies yesterday (re reference counting) I suggested that if state is flushed by etherealize, before the reference count goes to zero, that a pointer to a servant isn't especially useful. This is the case I had in mind. You can create your new servant, and you can call it via a local interface without trouble *until* you activate it. After that, it can be deactivated and etherealized at any time. Reference counting can guarantee that your servant hasn't been destroyed, but if you want to access anything about it that depends on it having valid state you are pretty much out of luck - some other servant may now have the state you are interested in. I don't like this situation, but I don't see any easy way out of it. Return-Path: Sender: "George Scott" Date: Thu, 23 Jul 1998 20:19:16 -0700 From: "George M. Scott" Organization: Inprise Corporation To: port-rtf@omg.org CC: orb_revision@omg.org, goldberg@inprise.com Subject: POA issues 1408,1409,1428, and 1627 I am sending in the current proposals for issues 1408, 1409, 1428 and 1627. It is critical that we reach consensus on these issues by the end of the day Friday (7/24) in order for these resolutions to be included in CORBA 2.3. Voting members of the previous Portability RTF please indicate if you are in favor or against the proposals by the 5pm PDT Friday. Jishnu is willing to move these issues to the Core RTF if we have consensus. The proposals for issues 1408/1409 and 1627 contain two sub-proposals. Please indicate which sub-proposal you favor in your response. Inprise will vote as follows: 1408/1409 - Yes for b. 1428 - Yes. 1627 - Yes for b. However, if there is consensus for the "a" variants of our proposal we are willing to change our vote to get resolution to these issues. Thanks. George P.S. I will be away from the office all day Friday, so comments on the proposal should be sent to Jon Goldberg (goldberg@inprise.com). Return-Path: Date: Thu, 23 Jul 1998 22:22:51 -0700 From: George Scott To: port-rtf@omg.org CC: orb_revision@omg.org Subject: Issue 1627: POA::deactivate_object() Here is our current proposal for issue 1627. There are two sub-proposals (a and b). The (a) proposal is similiar to what we have proposed before in that the object behaves as if the POA were in the holding state during deactivation. This can potentially deadlock as we have previously discussed, so we have an alternative proposal (b) which does not deadlock. In proposal (b) the object will not be deactivated until all requests have completed execution, it does not prevent new requests from executing, so there is no chance of deadlock. The object will only be deactivated when there are no active requests. If a user wants different behavior, similar to (a) they may use the POAManager to change the state to holding or some other state before invoking deactivate_object. Either proposal is straight forward to implement. We prefer (b) over (a) but will go with the consensus on this issue to reach resolution. We believe (b) provides the most flexibility to the user and is deadlock free. If a user wants behavior similar to (a) they may use the POAManager as we have discussed. George ------------------------------------------------------------------ Issue 1627: Problems with deactivate_object() Nature: Revision Summary: deactivate_object behavior is not defined when multiple concurrent active requests are executing in an object when it is deactivated. Resolution: Accepted for Corba RTF 2.3 Revision: Replace the second paragraph describing deactivate_object on page 9-35, section 9.3.8 with the following: (editorial note: choose one of paragraph A or B below) A. This operation causes the ObjectId specified in the oid parameter to be deactivated. An ObjectId which has been deactivated cannot receive new requests until the ObjectId has been removed from the Active Object Map. Any new requests which arrive for a deactivated ObjectId will behave as if the POA's POAManager was in the holding state. A deactivated ObjectId is removed from the Active Object Map when all requests executing for that ObjectId have completed. If a servant manager is associated with the POA, ServantActivator::etherealize will be invoked with the oid and the associated servant after the ObjectId has been removed from the Active Object Map. Once an ObjectId has been removed from the Active Object Map and etherealized (if necessary) it may then be reactivated through the usual mechanisms. B. This operation causes the ObjectId specified in the oid parameter to be deactivated. An ObjectId which has been deactivated continues to process requests until there are no active requests for that ObjectId. A deactivated ObjectId is removed from the Active Object Map when all requests executing for that ObjectId have completed. If a servant manager is associated with the POA, ServantActivator::etherealize will be invoked with the oid and the associated servant after the ObjectId has been removed from the Active Object Map. Once an ObjectId has been removed from the Active Object Map and etherealized (if necessary) it may then be reactivated through the usual mechanisms. The operation does not wait for requests or etherealization to complete and always returns immediately after deactivating the ObjectId. Return-Path: Sender: jon@floorboard.com Date: Thu, 23 Jul 1998 23:22:28 -0700 From: Jonathan Biggar To: "George M. Scott" CC: port-rtf@omg.org, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <35B7FD34.FCF9AC38@inprise.com> George M. Scott wrote: > > I am sending in the current proposals for issues 1408, 1409, 1428 > and > 1627. It is critical that we reach consensus on these issues by the > end of the day Friday (7/24) in order for these resolutions to be > included > in CORBA 2.3. Voting members of the previous Portability RTF please > indicate if you are in favor or against the proposals by the 5pm PDT > Friday. Jishnu is willing to move these issues to the Core RTF if > we have consensus. > > The proposals for issues 1408/1409 and 1627 contain two > sub-proposals. > Please indicate which sub-proposal you favor in your response. > > Inprise will vote as follows: > > 1408/1409 - Yes for b. > 1428 - Yes. > 1627 - Yes for b. > > However, if there is consensus for the "a" variants of our proposal > we > are willing to change our vote to get resolution to these issues. I also vote the same way: 1408/1409 - yes for b 1428 yes 1627 yes for b I like the new proposals. The only possible trouble left would be a case of livelock, where requests keep coming in for the object (or POA) continuously which prevent the deactivation or destruction from occurring. However, I expect this to be much less problematical than the previous deadlocking cases, and not too likely to occur anyway. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Fri, 24 Jul 1998 10:56:15 -0400 From: "Matthew A. Mihic" Organization: IONA Technologies, Inc. To: Paul H Kyzivat CC: "George M. Scott" , port-rtf@omg.org, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <35B7FD34.FCF9AC38@inprise.com> <35B8918F.3D3233AA@noblenet.com> Paul Kyzivat wrote: > 1627: I believe this should be deferred. Both options still have > problems and need more time to "bake". To explain further: > > 1627b has some potentially serious efficiency problems. It will > require > that pending deactivation be checked at the completion of every > invocation. This wouldn't be so bad except that it will require a > 2nd > lookup in the active object map at this time to check this. The need > for > this also appears to negate a lot of caching strategies for speeding > up > map lookups. I think that whether this causes efficiency problems is highly dependent on the POA implementation. For example, IONA's implementation does not require a double map lookup to handle this. Naturally, I won't be sharing any details of this implementation ... ;-) > 1627 a&b also lead to usage problems with no obvious solution. Once > deactivation has been requested, that objectId is in a limbo > state. An > attempt to explicitly activate will have to fail, but a caller > wanting > to do this has no way to wait for the state to change, and so will > be > reduced to active polling or outright failure. Making > activate_object a > blocking operation is even worse. > > If I had to pick the lesser evil, I would vote for 1627a. I agree with the badness of making activate_object a blocking operation, but wouldn't this lead to 1627b instead of 1627a? In b, you can throw in ObjectAlreadyExists, in a, you must block in activate_object or throw exceptions for both activate and deactivate. Regards, Matt --------- Matthew A. Mihic IONA Technologies, Inc. Phone: +1-617-949-4302 Email: mmihic@iona.com Return-Path: Date: Fri, 24 Jul 1998 17:37:28 +0100 From: jhierro@jam.tid.es (Juan Jose Hierro Sureda) To: port-rtf@omg.org, gscott@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 Cc: orb_revision@omg.org, goldberg@inprise.com X-Sun-Charset: US-ASCII > > The proposals for issues 1408/1409 and 1627 contain two > sub-proposals. > Please indicate which sub-proposal you favor in your response. > > Inprise will vote as follows: > > 1408/1409 - Yes for b. > 1428 - Yes. > 1627 - Yes for b. > In respect to POA issues 1408/1409, Telefonica I+D votes yes for a In respect to POA issue 1627, Telefonica I+D votes yes for a I agree with Jon Biggar in that a possible trouble left for options b in proposals for 1408/1409 and 1627 would be a case of livelock, where requests keep coming in for the object (or POA) continuously which prevent the deactivation or destruction from occurring. However, I disagree with him and believe it would represent a serious problem, more problematic than the previous deadlocking cases which, I believe, can be avoided by the programmer if proposal a. is adopted on these issues. Regards, -- Juanjo Return-Path: Sender: jon@floorboard.com Date: Fri, 24 Jul 1998 08:41:17 -0700 From: Jonathan Biggar To: "Matthew A. Mihic" CC: Paul H Kyzivat , "George M. Scott" , port-rtf@omg.org, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <35B7FD34.FCF9AC38@inprise.com> <35B8918F.3D3233AA@noblenet.com> <35B8A08F.AA569902@iona.com> Matthew A. Mihic wrote: > > Paul Kyzivat wrote: > > > 1627: I believe this should be deferred. Both options still have > > problems and need more time to "bake". To explain further: > > > > 1627b has some potentially serious efficiency problems. It will > require > > that pending deactivation be checked at the completion of every > > invocation. This wouldn't be so bad except that it will require a > 2nd > > lookup in the active object map at this time to check this. The > need for > > this also appears to negate a lot of caching strategies for > speeding up > > map lookups. > > I think that whether this causes efficiency problems is highly > dependent > on the POA implementation. For example, IONA's implementation does > not > require a double map lookup to handle this. Naturally, I won't be > sharing any details of this implementation ... ;-) I am also aware of an implementation strategy that does not require a second lookup in the active object map. > > 1627 a&b also lead to usage problems with no obvious solution. Once > > deactivation has been requested, that objectId is in a limbo state. An > > attempt to explicitly activate will have to fail, but a caller wanting > > to do this has no way to wait for the state to change, and so will be > > reduced to active polling or outright failure. Making activate_object a > > blocking operation is even worse. > > > > If I had to pick the lesser evil, I would vote for 1627a. > > I agree with the badness of making activate_object a blocking operation, > but wouldn't this lead to 1627b instead of 1627a? In b, you can throw > in ObjectAlreadyExists, in a, you must block in activate_object or throw > exceptions for both activate and deactivate. The only case where this would be a problem would be if no servant manager is being used. However, I don't see this as a practical problem anyway. In this case, if someone calls deactivate_object() and later calls activate_object_with_id() with the same OID again, there is a window in between where the POA must raise OBJECT_NOT_EXIST for any incoming requests. This is not an acceptable use case, since an object should not be alive, appear dead and then come back to life again. On the other hand, if you are using a servant activator, then the application will be informed that the deactivation has completed by the call to etherealize(). Since the scenario that Paul fears should be avoided anyway, I don't see a problem with version b of the proposal. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Fri, 24 Jul 1998 12:00:00 -0400 From: Paul H Kyzivat Organization: NobleNet To: "Matthew A. Mihic" CC: "George M. Scott" , port-rtf@omg.org, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <35B7FD34.FCF9AC38@inprise.com> <35B8918F.3D3233AA@noblenet.com> <35B8A08F.AA569902@iona.com> Matthew A. Mihic wrote: > > Paul Kyzivat wrote: > > > 1627: I believe this should be deferred. Both options still have > > problems and need more time to "bake". To explain further: > > > > 1627b has some potentially serious efficiency problems. It will > require > > that pending deactivation be checked at the completion of every > > invocation. This wouldn't be so bad except that it will require a > 2nd > > lookup in the active object map at this time to check this. The > need > for > > this also appears to negate a lot of caching strategies for > speeding > up > > map lookups. > > I think that whether this causes efficiency problems is highly > dependent > on the POA implementation. For example, IONA's implementation does > not > require a double map lookup to handle this. Naturally, I won't be > sharing any details of this implementation ... ;-) Of course. I haven't spent a great deal of time looking for optimizations supporting the proposed changes yet since they are still only proposed, and even slight variations can have major effects on what is possible. Naturally, at the first opportunity, I will be looking for cases your implementation doesn't handle correctly because of its optimizations :) > > > 1627 a&b also lead to usage problems with no obvious > solution. Once > > deactivation has been requested, that objectId is in a limbo > state. > An > > attempt to explicitly activate will have to fail, but a caller > wanting > > to do this has no way to wait for the state to change, and so will > be > > reduced to active polling or outright failure. Making > activate_object a > > blocking operation is even worse. > > > > If I had to pick the lesser evil, I would vote for 1627a. > > I agree with the badness of making activate_object a blocking > operation, > but wouldn't this lead to 1627b instead of 1627a? In b, you can > throw > in ObjectAlreadyExists, in a, you must block in activate_object or > throw > exceptions for both activate and deactivate. As far as I can tell, both a&b either require activate_object to block, or to throw an exception during the (indeterminate) period while etherealization is pending. Return-Path: Sender: jon@floorboard.com Date: Fri, 24 Jul 1998 09:12:45 -0700 From: Jonathan Biggar To: Juan Jose Hierro Sureda CC: port-rtf@omg.org, gscott@inprise.com, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <9807241625.AA06876@jam.tid.es> Juan Jose Hierro Sureda wrote: > > > > > I am sending in the current proposals for issues 1408, 1409, 1428 > and > > 1627. It is critical that we reach consensus on these issues by > the > > end of the day Friday (7/24) in order for these resolutions to be > included > > in CORBA 2.3. Voting members of the previous Portability RTF > please > > indicate if you are in favor or against the proposals by the 5pm > PDT > > Friday. Jishnu is willing to move these issues to the Core RTF if > > we have consensus. > > > > The proposals for issues 1408/1409 and 1627 contain two > sub-proposals. > > Please indicate which sub-proposal you favor in your response. > > > > Telefonica votes NO to adoption of proposal 1428, for the same > reasons stated the last time this proposal was voted. Attached is > a copy of the rationale I provide at that time: Did you forget your rationale? > > 1428: Blocking POA operations > > Proposal: Clarification 7/8 > > Yes: Mischkinsky, Mukerji, Giddings > > No: Kukura > > > > I vote NO on this proposal. My rationale is that it would prevent > usage of CORBA objects to admin servers (e.g., usage of an Admin > CORBA object > at each server that exports a shutdown operation which effectively > shuts down the server where it is executing > > module Server { > interface Admin { > ... > void shutdown (); > }; > > ). > > The proposal currently being discussed doesn't allow a simple > implementation > of the Admin::shutdown operation based on invoking ORB::shutdown: > the > invocation of ORB::shutdown inside the method that implements > operation > Admin::shutdown would get a BAD_INV_ORDER exception. > > This short of administrative service is used in some products that > HP > and Telefonica I+D have developed together and may have already been > shipped. This proposal does not prevent your Admin object from working right! It still allows you to call shutdown, but only the non-blocking version. Using the blocking version in your implementation of Server::Admin::shutdown() is problematical anyway, since there is no guarantee that a response can be sent once the ORB is shutdown. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: jon@floorboard.com Date: Fri, 24 Jul 1998 10:54:07 -0700 From: Jonathan Biggar To: Juan Jose Hierro Sureda CC: port-rtf@omg.org, gscott@inprise.com, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <9807241831.AA07082@jam.tid.es> Juan Jose Hierro Sureda wrote: > The POAManagers associated to the ORB would be deactivated as a result > of invoking shutdown ... That means that no other request may invoke > the operation where shutdown was invoked ... Of course, the thread > where shutdown was invoked would not be able to invoke CORBA operations > after shutdown has returned (an exception would be returned) but would > be able to perform some work. > > With this behaviour, I don't see the deadlock ... Here is the scenario: request A invokes request B which calls shutdown in blocking mode. If request A is invoked in the context of an object local to the same orb as B, then you will get deadlock. Shutdown will block waiting for request A to complete, which never will, since it is waiting for request B to complete, which is blocked on shutdown. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Fri, 24 Jul 1998 18:57:46 +0100 From: jhierro@jam.tid.es (Juan Jose Hierro Sureda) To: jhierro@jam.tid.es, jon@floorboard.com Subject: Re: POA issues 1408,1409,1428, and 1627 Cc: port-rtf@omg.org, gscott@inprise.com, orb_revision@omg.org, goldberg@inprise.com X-Sun-Charset: US-ASCII > > Did you forget your rationale? > > > > 1428: Blocking POA operations > > > Proposal: Clarification 7/8 > > > Yes: Mischkinsky, Mukerji, Giddings > > > No: Kukura > > > > > > > I vote NO on this proposal. My rationale is that it would > prevent > > usage of CORBA objects to admin servers (e.g., usage of an Admin > CORBA object > > at each server that exports a shutdown operation which effectively > > shuts down the server where it is executing > > > > module Server { > > interface Admin { > > ... > > void shutdown (); > > }; > > > > ). > > > > The proposal currently being discussed doesn't allow a simple > implementation > > of the Admin::shutdown operation based on invoking ORB::shutdown: > the > > invocation of ORB::shutdown inside the method that implements > operation > > Admin::shutdown would get a BAD_INV_ORDER exception. > > > > This short of administrative service is used in some products > that HP > > and Telefonica I+D have developed together and may have already > been > > shipped. > > This proposal does not prevent your Admin object from working right! > It > still allows you to call shutdown, but only the non-blocking > version. > Using the blocking version in your implementation of > Server::Admin::shutdown() is problematical anyway, since there is no > guarantee that a response can be sent once the ORB is shutdown. > I may use the non-blocking version of ORB::shutdown to implement Server::Admin::shutdown but that wouldn't support the kind of semantics I would like to see in all cases. I would be more in favour of a proposal that states that: - shutdown would block until all request being processed by POAManagers associated to that ORB have completed except for processing of the request where shutdown was called (if called from a request dispatch thread) - the ORB effectively shutdowns (i.e., ORB::run returns) when all ORB processing is completed (this means that the ORB would effectively shut down after the thread that invoked ORB::shutdown actually finishes, if that thread was trigered to dispatch a request) Anyway, i still don't like the proposed solution so I maintain the NO vote ... I prefer to resolve this issue in the next RTF since it's important and I believe that, if we change it, we should change it forever ... Of course, i may be the only one who votes no :-) -- Juanjo Return-Path: Date: Fri, 24 Jul 1998 13:59:04 -0400 From: Bob Kukura Organization: IONA Technologies To: George Scott CC: port-rtf@omg.org, orb_revision@omg.org Subject: Re: Issue 1627: POA::deactivate_object() References: <35B81A2B.53F786B8@inprise.com> We prefer (b) on this issue, but it also needs a bit of work before we can vote YES. See below: George Scott wrote: > > Here is our current proposal for issue 1627. > > There are two sub-proposals (a and b). The (a) proposal is similiar > to what we have proposed before in that the object behaves as if the > POA were in the holding state during deactivation. This can > potentially > deadlock as we have previously discussed, so we have an alternative > proposal (b) which does not deadlock. > > In proposal (b) the object will not be deactivated until all > requests > have completed execution, it does not prevent new requests from > executing, so there is no chance of deadlock. The object will only > be deactivated when there are no active requests. If a user wants > different behavior, similar to (a) they may use the POAManager to > change the state to holding or some other state before invoking > deactivate_object. > > Either proposal is straight forward to implement. We prefer (b) > over (a) but will go with the consensus on this issue to reach > resolution. We believe (b) provides the most flexibility to the > user and is deadlock free. If a user wants behavior similar to > (a) they may use the POAManager as we have discussed. > > George > > ------------------------------------------------------------------ > Issue 1627: Problems with deactivate_object() > Nature: Revision > > Summary: deactivate_object behavior is not defined when multiple > concurrent active requests are executing in an object > when it is deactivated. > > Resolution: Accepted for Corba RTF 2.3 > > Revision: Replace the second paragraph describing deactivate_object > on page 9-35, section 9.3.8 with the following: > > (editorial note: choose one of paragraph A or B below) > > A. This operation causes the ObjectId specified in the oid parameter > to be deactivated. An ObjectId which has been deactivated cannot > receive new requests until the ObjectId has been removed from the > Active Object Map. Any new requests which arrive for a deactivated > ObjectId will behave as if the POA's POAManager was in the holding > state. A deactivated ObjectId is removed from the Active Object Map > when all requests executing for that ObjectId have completed. If a > servant manager is associated with the POA, > ServantActivator::etherealize will be invoked with the oid and the > associated servant after the ObjectId has been removed from the > Active > Object Map. Once an ObjectId has been removed from the Active > Object > Map and etherealized (if necessary) it may then be reactivated > through > the usual mechanisms. > > B. This operation causes the ObjectId specified in the oid parameter > to be deactivated. An ObjectId which has been deactivated continues > to process requests until there are no active requests for that > ObjectId. A deactivated ObjectId is removed from the Active Object > Map when all requests executing for that ObjectId have completed. If > a > servant manager is associated with the POA, > ServantActivator::etherealize will be invoked with the oid and the > associated servant after the ObjectId has been removed from the > Active > Object Map. Once an ObjectId has been removed from the Active > Object > Map and etherealized (if necessary) it may then be reactivated > through > the usual mechanisms. > > The operation does not wait for requests or etherealization to > complete and always returns immediately after deactivating the > ObjectId. We still need to say what happens to activate calls during etherealization. Incarnation is already serialized with etherealization, and we believe explicit activation should also block during etherealization. -Bob Return-Path: Date: Fri, 24 Jul 1998 19:31:18 +0100 From: jhierro@jam.tid.es (Juan Jose Hierro Sureda) To: jhierro@jam.tid.es, jon@floorboard.com Subject: Re: POA issues 1408,1409,1428, and 1627 Cc: port-rtf@omg.org, gscott@inprise.com, orb_revision@omg.org, goldberg@inprise.com X-Sun-Charset: US-ASCII > > Juan Jose Hierro Sureda wrote: > > I would be more in favour of a proposal that states that: > > > > - shutdown would block until all request being processed by > POAManagers > > associated to that ORB have completed except for processing of > the > > request where shutdown was called (if called from a request > dispatch > > thread) > > > > - the ORB effectively shutdowns (i.e., ORB::run returns) when > > all ORB processing is completed (this means that the ORB would > > effectively shut down after the thread that invoked > ORB::shutdown > > actually finishes, if that thread was trigered to dispatch a > > request) > > This can still deadlock if the request that calls shutdown is in > turn > invoked by the implementation of another request in the same ORB. > The POAManagers associated to the ORB would be deactivated as a result of invoking shutdown ... That means that no other request may invoke the operation where shutdown was invoked ... Of course, the thread where shutdown was invoked would not be able to invoke CORBA operations after shutdown has returned (an exception would be returned) but would be able to perform some work. With this behaviour, I don't see the deadlock ... > > Anyway, i still don't like the proposed solution so I maintain > > the NO vote ... I prefer to resolve this issue in the next RTF > > since it's important and I believe that, if we change it, we > > should change it forever ... > > Nothing is forever... :-) Of course I don't want to change > something > and discover a problem in the new version that is as bad or worse > than > what we had before. Ultimately, however, it just has to come down > to > our best judgement at the time. > That's the point: I don't want to change something until I'm sure (or believe I'm sure :-) that I will not discover a problem in the new version that is as bad or worse than what we had before. -- Juanjo Return-Path: Sender: jon@floorboard.com Date: Fri, 24 Jul 1998 11:39:52 -0700 From: Jonathan Biggar To: Bob Kukura CC: George Scott , port-rtf@omg.org, orb_revision@omg.org Subject: Re: Issue 1627: POA::deactivate_object() References: <35B81A2B.53F786B8@inprise.com> <35B8CB68.8A7E0D29@iona.com> Bob Kukura wrote: > We still need to say what happens to activate calls during > etherealization. Incarnation is already serialized with > etherealization, and we believe explicit activation should also > block > during etherealization. I agree with this change. The only way I could see that this could cause a potential deadlock were if an operation implementation of an object attempted to reactivate the object, which is pure nonsense. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Fri, 24 Jul 1998 12:00:15 -0700 From: "Jon Goldberg" Reply-To: goldberg@inprise.com To: Juan Jose Hierro Sureda CC: jon@floorboard.com, port-rtf@omg.org, gscott@inprise.com, orb_revision@omg.org Subject: Re: POA issues 1408,1409,1428, and 1627 References: <9807241757.AA07022@jam.tid.es> Juan Jose Hierro Sureda wrote: > > > > > Did you forget your rationale? > > > > > > 1428: Blocking POA operations > > > > Proposal: Clarification 7/8 > > > > Yes: Mischkinsky, Mukerji, Giddings > > > > No: Kukura > > > > > > > > > > I vote NO on this proposal. My rationale is that it would > prevent > > > usage of CORBA objects to admin servers (e.g., usage of an Admin > CORBA object > > > at each server that exports a shutdown operation which > effectively > > > shuts down the server where it is executing > > > > > > module Server { > > > interface Admin { > > > ... > > > void shutdown (); > > > }; > > > > > > ). > > > > > > The proposal currently being discussed doesn't allow a simple > implementation > > > of the Admin::shutdown operation based on invoking > ORB::shutdown: the > > > invocation of ORB::shutdown inside the method that implements > operation > > > Admin::shutdown would get a BAD_INV_ORDER exception. > > > > > > This short of administrative service is used in some products > that HP > > > and Telefonica I+D have developed together and may have already > been > > > shipped. > > > > This proposal does not prevent your Admin object from working > right! It > > still allows you to call shutdown, but only the non-blocking > version. > > Using the blocking version in your implementation of > > Server::Admin::shutdown() is problematical anyway, since there is > no > > guarantee that a response can be sent once the ORB is shutdown. > > > > I may use the non-blocking version of ORB::shutdown to implement > Server::Admin::shutdown but that wouldn't support the kind of > semantics I would like to see in all cases. > > I would be more in favour of a proposal that states that: > > - shutdown would block until all request being processed by > POAManagers > associated to that ORB have completed except for processing of > the > request where shutdown was called (if called from a request > dispatch > thread) I just want to point out that you are always free to have your application explicitly put POAManagers in any state you'd like (holding/deactivated) if you want explicit behavior with respect to other requests. You can then invoke shutdown. This proposal only clears up rules for the implicit case and does a good job of eliminating deadlock for those cases. We cannot deal with every case implicitly, so I'm strongly in favor of making deadlocks as rare as possible when things are done implicitly, while making sure that applications that know a lot about what they are doing still have the necessary hooks to get any other reasonable behavior by explicitly using those hooks. George's proposal satisfies both of those goals. take care, Jon Return-Path: Date: Fri, 24 Jul 1998 12:10:51 -0700 From: "Jon Goldberg" Reply-To: goldberg@inprise.com To: Jonathan Biggar CC: kukura@iona.com, gscott@inprise.com, orb_revision@omg.org, port-rtf@omg.org Subject: Re: Issue 1627: POA::deactivate_object() References: <35B81A2B.53F786B8@inprise.com> <35B8CB68.8A7E0D29@iona.com> Jonathan Biggar wrote: > > Bob Kukura wrote: > > > We still need to say what happens to activate calls during > > etherealization. Incarnation is already serialized with > > etherealization, and we believe explicit activation should also > block > > during etherealization. > > I agree with this change. The only way I could see that this could > cause a potential deadlock were if an operation implementation of an > object attempted to reactivate the object, which is pure nonsense. I agree as well. Similar to the POA being destroyed, once apparent destruction has occurred, calls will block until actual destruction is complete. -Jon Return-Path: Date: Fri, 24 Jul 1998 12:18:09 -0700 From: "Jon Goldberg" Reply-To: goldberg@inprise.com To: Jonathan Biggar CC: Bob Kukura , gscott@inprise.com, orb_revision@omg.org, port-rtf@omg.org Subject: Re: Issue 1428: Blocking ORB/POA operations References: <35B81A12.611B5C59@inprise.com> <35B8D180.5690FFEF@inprise.com> <35B8DADF.54425B9B@floorboard.com> Jonathan Biggar wrote: > > Jon Goldberg wrote: > > > > But this dependency between ORB and POA instances in > > the same process is necessary to prevent deadlock. Consider > > the case where you have two POA's POA_A and POA_B in > > the same process. > > > > You invoke a request on an object managed by POA_A, which > > then invokes a request on an object managed by POA_B. The > > implementation of that request invokes shutdown with > > blocking set to TRUE. This will deadlock. > > > > There really isn't a dependency between ORBs/POAs as > > George proposed it. It just limits the number > > of places you can use blocking calls. A given implementation > > of shutdown need not know anything distinction between > > the target ORB and the currently dispatched ORB, it only > > need know that an invocation is in progress and > > therefore blocking cannot be used. This information is > > already known without any additional dependencies being > > added. As such, I don't think the wording change is > > required or beneficial. > > No, the distinction is that if you have two ORBs in the same > process, > then if, in the context of a request in ORB 1, a call to ORB 2's > shutdown is made with blocking true, this should be ok. Given that > the > two ORBs may be implemented by different vendors, there may not even > be > a way for ORB 2 to determine that the call was made in ORB 1's > context > anyway. Ok. I see that now. Unfortunately, the deadlock I point out above is possible with Bob's rewording. Since it still fixes the most common cases, I'm fine with the change. -Jon Return-Path: Date: Fri, 24 Jul 1998 23:11:47 -0400 From: Paul H Kyzivat Organization: NobleNet To: Juan Jose Hierro Sureda CC: jon@floorboard.com, port-rtf@omg.org, gscott@inprise.com, orb_revision@omg.org, goldberg@inprise.com Subject: Re: POA issues 1408,1409,1428, and 1627 References: <9807241831.AA07082@jam.tid.es> Juan Jose Hierro Sureda wrote: > The POAManagers associated to the ORB would be deactivated as a > result > of invoking shutdown ... That means that no other request may > invoke > the operation where shutdown was invoked ... Of course, the thread > where shutdown was invoked would not be able to invoke CORBA > operations > after shutdown has returned (an exception would be returned) but > would > be able to perform some work. The ORB shutdown cannot complete with an operation outstanding, for many reasons. Here is one: the POA containing the object-that-is-in-an-invocation must be destroyed before shutdown is complete. This may require etherealization of that very object. But it cannot be etherealized until the operation is complete. You seem to be asking someone to commit suicide and report back that he has successfully done so, buried himself, and planted grass and a proper headstone on the grave. This isn't really possible. Return-Path: Sender: jon@floorboard.com Date: Fri, 24 Jul 1998 20:38:33 -0700 From: Jonathan Biggar To: Paul H Kyzivat CC: Bob Kukura , George Scott , port-rtf@omg.org, orb_revision@omg.org Subject: Re: Issue 1627: POA::deactivate_object() References: <35B81A2B.53F786B8@inprise.com> <35B8CB68.8A7E0D29@iona.com> <35B9493F.14C7C11E@noblenet.com> Paul H Kyzivat wrote: > > Bob Kukura wrote: > > We still need to say what happens to activate calls during > > etherealization. Incarnation is already serialized with > > etherealization, and we believe explicit activation should also > block > > during etherealization. > > This seems like a very bad idea to me. > Serializing incarnation and etherealization is ok because they are > inherently asynchronous tasks. But activate_object is likely to be > called with the expectation that it will return with all due haste. > > I consider it the lesser of evils that it throw an exception in this > case, allowing the caller to decide what to do. > > I do agree that it is necessary to specify what happens. But then you have left the application with no way to find out when to call activate_object() again. I think it is better for it to block, since typically the next step after activate_object is to get its reference, which won't work unless the object is properly activated. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Date: Sat, 25 Jul 1998 16:15:22 -0700 From: "Jon Goldberg" Reply-To: goldberg@inprise.com To: orb_revision@omg.org CC: port-rtf@omg.org Subject: Issue 1627: POA::deactivate_object Hi Folks- Here is the revised text for resolving 1627. It is George's proposal with item B selected over A, and an additional clarifying statement suggested by Bob Kukura. This clarification is that any reactivation attempt will block until etherealization is complete. This includes implicit and explicit reactivation (implicit is already taken into account in the description of "etherealize" in CORBA 2.2). This represents the informal consensus of the voting members of the portability RTF. By informal, I mean all the vocal members agreed to this text. No formal vote was taken. Feel free to disagree with my assessment of the situation. Given the "gentlemen's agreement" between the core and portability RTFs, I think these can now be voted on by the core RTF. Jishnu's deadline is probably pretty close (sometime on Monday?) so please vote quickly. If Jishnu could send out the voting list one more time, I'd appreciate it. thanks, Jon ------------------------------------------------------------------ Issue 1627: Problems with deactivate_object() Nature: Revision Summary: deactivate_object behavior is not defined when multiple concurrent active requests are executing in an object when it is deactivated. Resolution: Accepted for Corba RTF 2.3 Revision: Replace the second paragraph describing deactivate_object on page 9-35, section 9.3.8 with the following: This operation causes the ObjectId specified in the oid parameter to be deactivated. An ObjectId which has been deactivated continues to process requests until there are no active requests for that ObjectId. A deactivated ObjectId is removed from the Active Object Map when all requests executing for that ObjectId have completed. If a servant manager is associated with the POA, ServantActivator::etherealize will be invoked with the oid and the associated servant after the ObjectId has been removed from the Active Object Map. Reactivation for the ObjectId blocks until etherealization (if necessary) is complete. This includes implicit activation (as described in "etherealize" on page 9-23) and explicit activation via POA::activate_object_with_id(). Once an ObjectId has been removed from the Active Object Map and etherealized (if necessary) it may then be reactivated through the usual mechanisms. The operation does not wait for requests or etherealization to complete and always returns immediately after deactivating the ObjectId.