[whatwg] onclose events for MessagePort

Jonas Sicking jonas at sicking.cc
Fri Oct 18 17:26:45 PDT 2013

On Thu, Oct 17, 2013 at 2:08 PM, Ehsan Akhgari <ehsan at mozilla.com> wrote:
>> 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.
> I'm not sure if I understand this.  If the MessagePort exists on the side
> that is interested to handle the event, then it can't be GCed on the other
> side either, right?

I thought the proposal was to not fire "channeldropped" when the
channel is GCed. Thus allowing channels with both "message" and
"channeldropped" event listeners on either side to still be GCed. Is
that correct?

If so, that exposes GC behavior. If at some point both pages that hold
on to an endpoint of a message channel drop their references the
channel can get GCed. If it is GCed no events fire.

However if the page holding on to either port crashes before the GC
happens, then the "channeldropped" event is fired on the other port.

Hence the timing of the GC affects whether "channeldropped" is fired.
Hence GC behavior is exposed.

>> 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.
> Exposing this state as a property will make people who have use cases such
> as "Update the UI if this other tab/page/app/etc is killed" poll the
> attribute, which seems non-ideal to me.

I don't see a way to simultaneously fulfill all of the following constraints:

1. Don't expose GC.
2. Provide a callback when the other side crashes or lives in a thread
that dies.
3. Enable GC of channels where neither side referenced.

What I think might work is to say that as long as a "channeldropped"
event listener is registered with a port, that is equivalent to
holding a strong reference to the port. I.e. that prevents the channel
from being GCed. Even if no references are held to either port.

In other words, we'd give up 3, but only when 2 is actively used.

And then define that "channeldropped" is fired on a port whenever the
other side is killed due to either living in a process that crashes,
or living in a thread that is closed or terminated.

We would also need to define that the "channeldropped" event is never
fired on a port if that port's *owning* window has been navigated away
from. Otherwise we could *never* GC a channel between two windows that
has "channeldropped" registered on either side.

So the expectation is that a caller should only register a
"channeldropped" event if it's actively waiting for a response from
that thread. It's not something that you should register when creating
the port and then never unregister. Having a "channeldropped" event
listener registered can cause a whole worker thread to be kept alive
longer than it otherwise would.

We could further define that "channeldropped" is fired when the owner
of the *other side* is navigated away from. This would mean that
events can be received even after a "channeldropped" event has been
fired since other windows could still hold a reference to the port and
send messages through it. However it would allow us to release the
strong reference that the "channeldropped" event listener implicitly
creates as soon as either side is navigated away from.

> Also, having a setTimeout(0) loop which polls the attribute would open us to
> the exact same risks as the event would, I think.

How do you mean? Which risks in particular are you referring to?

/ Jonas

More information about the whatwg mailing list