[whatwg] onclose events for MessagePort

Ehsan Akhgari ehsan at mozilla.com
Mon Oct 21 18:05:42 PDT 2013


On Fri, Oct 18, 2013 at 8:26 PM, Jonas Sicking <jonas at sicking.cc> wrote:

> 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?
>

Yes, that's 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.
>

Yeah, I see the problem now.


>  >> 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.
>

This sounds good to me.


> 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.
>

Right.


> 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.
>

But what if the page is navigated back to?  I think this implies that
having fired a "channeldropped" event because of this reason means that the
UA needs to make it impossible to navigate back to the same window, which
means disabling optimizations such as Gecko's back-forward cache, which
sucks.


> > 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?


I was talking about GC observabiity, but I think I was wrong since the
attribute that you were proposing could not be queried if you lost the
reference to it from js...

Cheers,
--
Ehsan
<http://ehsanakhgari.org/>


More information about the whatwg mailing list