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.