[whatwg] Sending MessagePorts after they have started

Hi All,

It is currently possible (I think) to send a port through postMessage
after the port was started. This makes sending ports across processes
(such as to an iframe or worker living in a different process) pretty
painful to implement. It also makes it hard to define without causing
race conditions.

What you have to do:
Say that port B and port C are entangled and live in separate
processes, lets call the processes 2 and 3. Both ports are started. A
message is posted to port B which means that it should arrive to port
C.

The implementation sends a IPC message from process 2 to process 3
that says that a message should be fired on C.

However before that IPC message is processed, script decides to
forward port C to another iframe, this iframe is running in process 4.

The implementation sends a IPC message to process 4 saying that a new
port should be created, port D, and that it should be entangled with
port B living in process 2. It also sends a IPC message to process 2
saying that port B is now entangled with port D in process 4.

Process 3 now receives the IPC message from process 2 saying that a
message should be fired on port C.

The implementation now has to send an IPC message to process 4 saying
to fire the message to port D instead.

Process 2 now receives the IPC message from process 3 saying that port
B is now entangled with port D in process 4 and updates its data
structures to reflect that.

The script in process 2 now calls postMessage on port B to send a
second message.

The implementation sends an IPC message to process 4 saying that a
message event should be fired on port D.

This IPC message arrives immediately to process 4 saying that port D
should fire a message event. However the implementation must now
detect that this message was received out-of-order (through for
example a ID counter in the sending port) and queue it.

Finally the IPC message from process 3 to process 4 arrives about the
first message event and both message events can be fired in order.


Things get hairier if somewhere along this the scripts decided to
forward port B in process 2 to an iframe run by process 1. Then you
have to proxy the 'port B is now entangled with port D in process 4'
message on to process 1 which means that even more messages can go to
the wrong place and be proxied to the correct process and port.

There are alternative implementation strategies. The simplest one is
probably to never tell the other end when a port is moved, instead set
up a permanent proxy and forward all message through the full chain of
processes that the ports have passed through. Another strategy is to
require that each message is acknowledged and resend messages if a
port end was retangled before the message got processed.


It's also hard to specify this without race conditions since you have
to deal with the situation that a port has been retangled after a
message was queued for it to fire against the port.


To fix all this I propose that if a port has been started, we don't
allow it to be passed to postMessage. If that is done an exception is
thrown.

This way ports can queue all outgoing messages until they receive word
that the other port has been opened. Then messages can always be sent
to a known address that will never move. I can't think of any use case
that this would disable.

You still have to deal with getting the information about that a port
has been opened and where it lives to the other port. But this is
somewhat simpler.

/ Jonas

Received on Thursday, 13 November 2008 21:50:34 UTC