On May 29, 2009, at 11:29 AM, Drew Wilson wrote:



On Thu, May 28, 2009 at 7:47 PM, Maciej Stachowiak <m...@apple.com> wrote:

On May 28, 2009, at 5:17 PM, Ian Hickson wrote:

On Thu, 28 May 2009, Maciej Stachowiak wrote:
On May 28, 2009, at 1:08 PM, Ian Hickson wrote:
On Thu, 28 May 2009, Maciej Stachowiak wrote:

If so, that seems like it could create unbounded memory leaks in
long-running Web applications that use MessagePorts, even if all
references to both endpoints of the MessageChannel are dropped. That
seems unacceptable to me, unless I misunderstood.

The requirement is actually indistinguishable from the UA using the
other alternative and just having a really slow garbage collector that
only runs at page-closing time.

So it's exactly equivalent to the old requirement, except the spec now
specifically points out that you can just leak forever instead. I don't
think that addresses the original concern at all.

I've tweaked the text some to make it clear that once the port is not
entangled, it doesn't continue being protected in this way.

The new text seems to be this:

"When a MessagePort object is entangled, user agents must either act as if the object has a strong reference to its entangledMessagePort object, or as if the MessagePort object's owner has a strong reference to the MessagePort object"

It seems to me this allows the following case: two message ports A and B are entangled. A is treated as having a strong reference to B, but is not treated as if its owner has a strong reference to it. However, B is not treated as having a strong reference to A, but is treated as if its owner has a strong reference to it. Is that intended? I think this behavior would be practically implementable and quite useful in many cases, even though it is asymmetric. But I am not sure if the text intended to allow it.

Can you elaborate on this a bit? Where would this asymmetric behavior be useful? It seems like in the specific case you cite, B would be doubly-referenced, while A would be unreferenced.

Ian clarified on IRC that he didn't mean to allow it. The reason it would be useful is that it would allow A to be garbage collected as soon as it has no references, at which point it can notify B that it's gone, and then B can switch rules, and itself be garbage collected once it has no references. It would prevent memory leaks but would not provide meaningful limits on nondeterminism.

Regards,
Maciej

P.S. In case anyone doubts that distributed GC is hard (as apparently Ian did until yesterday), here is a clarifying example. It might seem simple to come up with a protocol for two MessagePorts to tell each other when they are otherwise unreferenced by anything in their own heap with minimal GC hooks. But suppose you have Workers A and B, and Window W, and a MessageChannel connecting each pair. The MessagePorts are AB-A (the endpoint of the AB channel in A), AB-B, AW-A, AW-W, BW- B, BW-W. Now suppose that the two MessagePorts in each global context indirectly reference each other (so AB-A has a reference to AW-W and vice vera and so forth). It's quite hard to come up with a protocol that will let all six MessagePorts know that they have no references besides each other and thus may be garbage collected. Note that this example can easily arise in practice, for example if the onmessage listeners for each message port are closures with both the relevant ports in scope. Note also that distributed GC among 3 heaps is still a much simpler special case than the fully general case of N heaps. In practice, this means that any implementation with split heaps (which likely will include all multiprocess implementations) has to take the more conservative lifetime rule, tying to the owner. So in practice, the only way to reliably free the resources associated with a MessagePort will be to .close() it.

Reply via email to