[whatwg] Sending MessagePorts after they have started

Ian Hickson ian at hixie.ch
Mon Dec 15 17:37:54 PST 2008

On Thu, 13 Nov 2008, Jonas Sicking wrote:
> 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.

The implementation strategy you describe does indeed seem like it would be 
all kinds of pain to set up. However, it isn't the only strategy available 
and indeed I think some of the other strategies are more appropriate here.

Some of these other strategies include:

 * Using a Unix socket, Windows mailslot, or other communication mechanism 
   that is buffered, asynchronous, and can be passed between processes.
   With such a mechanism, when passing a port from one process or thread 
   to another, the source thread would just post an event to the 
   destination thread, and stop reading from the underlying pipe. The 
   receiving thread would then receive the event, and only when it was 
   ready to process a message from the pipe would it read from it -- if 
   the pipe was sent to be sent to another thread first, then it might in 
   fact never read from the pipe. Meanwhile, the other end of the pipe, 
   the thread with the other port, need not know any of this, and can be 
   writing to the pipe without worrying about messages getting lost.

 * Shared memory for the ports. Similar to the above strategy, one could 
   have a block of shared memory for each direction, with in each 
   direction one side being responsible for adding messages and marking 
   them new, and the other side being responsible for removing messages 
   and marking them read.

 * Proxying all messages through a single master message controller 
   thread. Instead of posting messages straight to the destination thread, 
   each cross-thread or cross-process pair of ports would have its 
   end-points registered with a single controlling thread or process. 
   Messages would then be sent to that thread/process, which would keep 
   them buffered while a port was being bounced around, and would only 
   actually send messages to the final destination when it was ready.

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

Yes, if IPC absolutely _must_ be done over cross-thread IPC without any 
sort of separate message channel to represent the pairs of ports, these 
are other options.

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

Good point. Fixed.

I also dropped MessagePort.onclose which had all kinds of weird race 
conditions. Currently the only way to know if a port is not entangled is 
to change its |active| attribute.

> 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 seems like it unnecessarily limits the power of message channels. 
What if you want to receive a message, and then defer to another thread if 
the message you receive is one asking for a particularly time-consuming 
process, but not if it is something simple?

Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

More information about the whatwg mailing list