Re: Simultaneous destructors
Benjamin Smedberg <[email protected]>
| Newsgroups | gmane.comp.mozilla.devel.dom |
|---|---|
| Message-ID | <[email protected]> |
On 9/17/09 4:25 PM, Chris Jones wrote:
> (1)
> Make destructor messages part of the protocol of the actors they
> destruct, rather than part of the manager's protocol. This would imply
> that dtors can't race with any other message (including other dtors),
> since dtors transition into a special _DEAD_ state. (I.e., the dtor and
> another message can never commute.) For example
>
> protocol PluginInstance {
> manages BrowserStream;
> parent: BrowserStream();
> // no more ~BrowserStream()
> }
>
> protocol BrowserStream {
> child: M1();
> parent: M2();
>
> child: delete();
> // could also be ~BrowserStream()
>
> state S1: send M1 goto S2;
> state S2; recv M2 goto DYING;
> state DYING: send delete;
> }
>
> This proposal adds a new keyword "delete" which is understood to mean
> "the destructor message for this protocol's actors." (We could also
> just reuse ~Protocol, it's just a syntax thing that I don't have strong
> feelings about.)
>
> I think this would work quite well ... except for "stateless" protocols
> like some in NPAPI. For them it's impossible to declare a non-racy
> destructor. They could be special-cased in that for them, IPDL would
> not treat sending a message to a nonexistent actor as a "fatal" error,
> only to the extent that doing so would cause a spurious fatal error.
> (Fancier implementations are possible.)
I don't understand how the extra state helps, at least if there are any
async messages involved:
protocol Channel {
child: dataavailable();
child: datadone()
parent: cancel();
parent: delete();
state NORMAL:
send dataavailable goto NORMAL;
send datadone goto DYING;
recv cancel goto DYING;
state DYING:
send delete;
}
Let's say the parent is sending dataavailable(). The child sends cancel()
and then immediately sends delete(). Unless the parent somehow acknowledges
that there has been a state transition to DYING, you could still end up
sending a message to a dead actor. This is almost exactly how I see necko
channels being modeled.
> (2)
> Keep dtors as part of the manager protocol, but only allow dtors to be
> uni-directional. I.e., |both: ~Subprotocol()| would be explicitly
> disallowed. Then, on the side that *sends* a particular dtor, receiving
> a message addressed to a nonexistent actor would no longer be fatal.
* Are protocol IDs re-used after destruction?
* If so, we need to make sure that we don't reassign the protocol ID until
we're sure the other side won't be sending a racy message to it.
(If they aren't re-used, aren't we likely to run out of IDs in normal
runtime situations?)
> (3)
> Do either or none of { (1), (2) }, and treat destructor messages as
> special in that the IPDL actors aren't "actually" destroyed until the
> other side ACKs the dtor message. That is, actors can continue to
> receive messages (though not send them) until the other side replies to
> the dtor message. It's not really clear what should happen when a
> "half-deleted" actor receives a message. Options:
> (a) IPDL automatically returns EDESTROYED or something like that
> (b) IPDL invokes a special handler that decides what to do
> (c) the actor is marked as DEAD, that state is visible to C++, and
> it's up to the implementation to take care of itself.
>
>
> Strong opinions? I lean towards (1) plus (3a), that is, use (3a) for
> stateless protocols.
Right now I don't see how #1 helps, so I'm leaning towards 3a or 3c. 3c has
the advantage that on the child side IPDL methods still cannot fail, which
avoids some error-checking code.
--BDS