[whatwg] onclose events for MessagePort

Andrew Wilson atwilson at google.com
Fri Oct 11 00:38:11 PDT 2013


On Thu, Oct 10, 2013 at 11:52 PM, Jonas Sicking <jonas at sicking.cc> wrote:

> On Thu, Oct 10, 2013 at 8:26 AM, Ehsan Akhgari <ehsan at mozilla.com> wrote:
> > On Thu, Oct 10, 2013 at 2:58 AM, Jonas Sicking <jonas at sicking.cc> wrote:
> >>
> >> On Wed, Oct 9, 2013 at 3:06 PM, Ehsan Akhgari <ehsan at mozilla.com>
> wrote:
> >> > OK, so I gave this some thought and I and Olli managed to convince
> each
> >> > other that finding a solution to the problem of dispatching a generic
> >> > onclose event is impossible since there is no deterministic point in
> >> > time
> >> > before a worker is GCed when we know that it will be GCed soon.
> >> >
> >> > So with that behind us, how about we add an explicit event to be fired
> >> > when
> >> > the other side of a message channel gets destroyed in a catastrophic
> way
> >> > which is not observable from the web content code running on that
> side,
> >> > such
> >> > as a process crash for example?  The basic idea behind why this more
> >> > restricted proposal is useful is that barring the catastrophic failure
> >> > case,
> >> > applications can detect the other cases why further communication may
> be
> >> > impossible (such as navigating away from the page) themselves and
> notify
> >> > the
> >> > other side of the channel as desired -- it is only the catastrophic
> >> > termination case which is not detectable from content script.
> >> >
> >> > How about we add another event named "channeldropped" (pending
> >> > bikeshedding)
> >> > which is fired on a message port if the owner global context of its
> >> > entangled port is terminated in a catastrophic way?  Needless to say,
> >> > the
> >> > event will be queued asynchronously with the termination of the other
> >> > side,
> >> > and it will not be affected by garbage collection.
> >>
> >> I could see the GC case not being solvable.
> >>
> >> But is there a reason that we couldn't also fire the event if the
> >> other side is forcefully terminated through a navigation or a
> >> Worker.terminate() call?
> >
> >
> > The reason I did not extend this to navigation and Worker.terminate() is
> > that at least in theory the authors should be able to detect those in
> their
> > application and use postMessage() to communicate that information if
> desired
> > (assuming that you can handle window.onunload and have control over the
> code
> > calling terminate(), respectively.)
> >
> > Although perhaps my argument is a bit weaker about terminate() than
> > navigation.
> >
> > Do you see a good reason why we should not leave those cases to authors?
>
> While technically possible for a webpage to handle ports that were
> passed to a worker and send a signal before the worker is terminated,
> it is really hard.
>
> First off it means that you have to create a separate MessageChannel
> just for the close-signal. You can't get the worker to to send the
> message without first finishing both the currently running task, and
> also processing all the tasks on the workers task queue. This would
> defeat the whole purpose of terminate(). So you need to keep a
> separate channel specifically to send the close message.
>
> Second, you need to track all the ports that are own by a specific
> worker so that you know which channels to send a close message for.
>
> Third, since the close message comes from a separate channel than
> other messages, it means that you have to deal with races. When you
> get a message from the separate channel that the main channel is
> dying, there might still be message in the pipe for the main channel.
> But there is no way to know when you got the last one. Timeouts are
> probably the only way, and that's obviously racy/slow.
>
> In short: The pain! It is burning!
>
> For navigation things are better since the caller can always use an
> onpagehide/onunload send a signal saying that the port is going away.
>
> It occurs to me that all of the proposals here does expose some amount
> of GC behavior. Even a "channeldropped" message which is sent only
> when the other side crashes exposes GC behavior. If GC happens to run
> before the crash and then collect the MessageChannel ports, then no
> channel exists at the time of crash, and thus no event is sent.
> However if the GC runs later, or if it doesn't successfully collect
> the MessageChannel ports, then the "channeldropped" event does fire.
>

Interesting. Section 5.3.1 of the MessagePort spec states that the ports
should only be GC'd if there are no references to either side and if there
are no pending messages for either port (basically, meaning that neither
port is reachable), but this "channeldropped" API provides a new way of
access.

So we'd need to update this part of the spec:

*Furthermore, a MessagePort
<http://www.w3.org/TR/webmessaging/#messageport> object
must not be garbage collected while there exists a message in a task queue that
is to be dispatched on that
MessagePort<http://www.w3.org/TR/webmessaging/#messageport> object,
or while the MessagePort <http://www.w3.org/TR/webmessaging/#messageport>
 object's port message
queue<http://www.w3.org/TR/webmessaging/#port-message-queue> is
open and there exists a
message<http://www.w3.org/TR/webmessaging/#event-message> event
in that queue.*

to add the following:

*"or while there exists an event listener on either port for the
channeldropped event."*


> That's not to say that this solution wouldn't work. Exposing some
> amount of GC behavior might be ok. But it does mean that we should
> have a realistic bar as we discuss expanding the event to more
> situations than just process crashes.
>
> One solution which I think would never expose GC behavior is to simply
> have a property on the MessagePort which indicates if the owner of the
> other side has been killed or navigated away from. No event would fire
> as that property changes value.
>
> Since it's a property, it can only be read if a reference to the
> MessagePort is being held. As long as such a reference exists neither
> side of the MessageChannel can be GCed.
>

I'm just concerned that this leads to people having to poll their ports.
But agreed that this also addresses the issue. I dimly recall at one point
we had a "closed" attribute which would be set on the ports whenever either
end had closed the port - we could resurrect that as well, and also set it
on an entangled port when a document is discarded.


>
> / Jonas
>
> >
> >>
> >>
> >> > --
> >> > Ehsan
> >> > <http://ehsanakhgari.org/>
> >> >
> >> >
> >> > On Tue, Oct 1, 2013 at 6:14 PM, Jonas Sicking <jonas at sicking.cc>
> wrote:
> >> >>
> >> >> On Tue, Oct 1, 2013 at 11:13 AM, Boris Zbarsky <bzbarsky at mit.edu>
> >> >> wrote:
> >> >> > On 10/1/13 2:11 PM, Ian Hickson wrote:
> >> >> >>
> >> >> >> How often do we expect two tabs to be talking to each other
> though?
> >> >> >
> >> >> > Or a page to an out-of-process subframe?
> >> >>
> >> >> Or an out-of-process worker. I would think that in Chrome
> >> >> SharedWorkers can come from a separate process, though that might
> >> >> change if/when chrome switches to out-of-process iframes.
> >> >>
> >> >> / Jonas
> >> >
> >> >
> >
> >
>



More information about the whatwg mailing list