Re: Simultaneous destructors
Chris Jones <[email protected]>
| Newsgroups | gmane.comp.mozilla.devel.dom |
|---|---|
| Message-ID | <[email protected]> |
Chris Jones wrote:
> Benjamin Smedberg wrote:
>> How does IPDL deal with destructors that are fired simultaneously from
>> both
>> sides, e.g. ~PBrowserStream? Even if we make one side "win the race",
>> won't
>> IPDL reject the second destructor message (because it has an invalid
>> actor
>> ID) and abort the process? If it doesn't abort the process, what is the
>> behavior (return values) of the second destructor message?
>>
>
> Right now, IPDL treats dtors as it does any other message, and by "any
> message" standards that's not a race.
>
> But this is just a good old fashioned bug, as dtors define an implicit
> transition, [alive]-->DEAD. I'll add this in soon.
>
Hmm, I was hasty in my response. On further consideration this is a
deeper problem.
There are two facets to the problem. The first mainly applies to
nominally stateless, inherently racy protocols like NPAPI. The example
you present with ~PBrowserStream forces a design decision: whether or
not to allow destructor messages to race. I would prefer to just
disallow racy destructors; I think there's a workaround for the NPAPI
(generally, crappy API) case. The workaround is two-phase destruction.
For example:
protocol PBrowserStream {
child: RequestDestruction; // first phase
parent: NotifyDestruction; // first phase
};
protocol PPluginInstance {
manages PBrowserStream;
parent: PBrowserStream;
~PBrowserStream; // second phase
};
(I'm not sure "which" NPStream the PBrowserStream models; I'm assuming
it's the one created with NPN_NewStream() and so sort of "owned" by the
child).
If the browser wants to destroy the BrowserStream, instead of directly
invoking the dtor, it destroys the "real" NPStream wrt to NPAPI and then
sends "RequestDestruction." In the common case, the plugin will be idle
wrt the stream and simply send back the actual ~PBrowserStream message.
If the plugin wants to destroy a BrowserStream, it first sends
"NotifyDestruction" to warn the browser. In the common case, the
browser will be idle wrt the stream, clean up the NPStream, and send
"RequestDestruction" back to the plugin, upon which ~PBrowserStream will
be sent.
If, however, RequestDestruction and NotifyDestruction race, it causes no
problems as the browser is guaranteed to have processed
NotifyDestruction *before* ~PBrowserStream arrives. The C++
implementations of browser stream actors just have to be careful not to
double-"free" the NPStreams.
That's one option, again (to me eyes) a hack around NPAPI limitations.
Another option for this case is to *allow* racy destructor messages.
All that has to be done in IPDL is, only for protocols with racy
destructors, not to blow up when a destructor references an unknown
actor. This approach trades a safety check for racy destructors. Both
are feasible and easy, but again I lean towards two-phase destruction.
I now see that the second facet of this problem isn't worth discussing
until we resolve this first issue.
Cheers,
Chris