[html5] Web Workers: Race-Condition setting onmessage handler?

Tobias Sauerwein tobias.sauerwein at camptocamp.com
Tue Aug 3 04:21:44 PDT 2010


On Mon, Aug 2, 2010 at 7:09 PM, Drew Wilson <atwilson at chromium.org> wrote:

> (sending from the correct address this time)
>
> On Mon, Aug 2, 2010 at 7:57 AM, Jeremy Orlow <jorlow at google.com> wrote:
>
>>
>>
>> ---------- Forwarded message ----------
>> From: Tobias Sauerwein <tobias.sauerwein at camptocamp.com>
>> Date: Tue, Jul 27, 2010 at 8:46 AM
>> Subject: [html5] Web Workers: Race-Condition setting onmessage handler?
>> To: help at lists.whatwg.org
>>
>>
>> Hi!
>>
>> I am wondering what prevents a web worker from running into
>> race-conditions when setting the onmessage handlers. I am worried about that
>> a web worker posts a message before the main script has set up the onmessage
>> handler, or the other way around, that the web worker posts a message before
>> the main script has set up its onmessage handler.
>>
>> I know that there is a message queue [1], but you can easily make up an
>> example where a message is not enqueued:
>>
>> Main Script:
>>
>> var worker = new Worker("webworker.js");
>>> worker.onmessage = function(event) {
>>>     console.log('onmessage ' + event.data)
>>> };
>>> worker.postMessage("start");
>>>
>>
>>
>> 'webworker.js':
>>
>> setTimeout(
>>>     function() {
>>>         onmessage = function(event) {
>>>             postMessage("message received");
>>>         };
>>>         postMessage("done");
>>>     }, 1000);
>>>
>>
>>
>> The output is (in Chromium 6.0.475.0 and Firefox 4.01b, Opera 10.70 also
>> outputs "onmessage message received"):
>>
>> onmessage done
>>>
>>
>> So the "onmessage" handler of the web worker is never called.
>>
>>
>> Is this the behavior the specification requests, or is it a bug in
>> Chrome/Chromium and Firefox?
>>
>> Tobias
>>
>>
>>
>> [1]:
>> http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#port-message-queue
>>
>> _______________________________________________
>> Help mailing list
>> Help at lists.whatwg.org
>> http://lists.whatwg.org/listinfo.cgi/help-whatwg.org
>>
>>
>> This is the correct behavior. If there is no onmessage event at the time
> that an event arrives at the worker's event loop, it will be dropped on the
> floor. The reason this happens is steps 7/8 in section 4.5 of the worker
> spec:
>
> 7. Jump to the script's *initial code entry-point*, and let that run until
> it either returns, fails to catch an exception, or gets prematurely aborted
> by the "kill a worker<http://www.whatwg.org/specs/web-workers/current-work/#kill-a-worker>"
> or "terminate a worker<http://www.whatwg.org/specs/web-workers/current-work/#terminate-a-worker>"
> algorithms defined below.
> 8. If worker global scope is actually a DedicatedWorkerGlobalScope<http://www.whatwg.org/specs/web-workers/current-work/#dedicatedworkerglobalscope> object
> (i.e. the worker is a dedicated worker), then enable the port message
> queue of the worker's implicit port.
>
> Basically, once the initial worker script returns, the worker's port is
> enabled and the normal message port event delivery mechanism kicks in
> (including dropping unhandled messages on the floor). I can't say whether
> Opera's behavior is correct or not based on your description - if you
> increase the timeout from 1 second to 10 seconds, do you still get the
> "onmessage message received"? If so, then that may be a bug in Opera because
> events delivered to workers without an onmessage handler set should be
> dropped.
>
> -atw
>
>
Hi Drew,
thanks for your reply!

If I set the timeout to 10 seconds, the message is still delivered in Opera.


... because events delivered to workers without an onmessage handler set
> should be dropped.
>

But if this is the case, then there is a big race-condition. Or I am totally
wrong.. :)

Let me give you an example:

The main script:
var myWorker = new Worker('worker.js');
myWorker.onmessage = function(evt) {..};
myWorker.postMessage('start');
//..

The web worker:
onmessage = function(evt) {
  // do calculation
  // post result
};

I guess this is the common structure: The web worker starts its work when it
receives a message.

But now the execution path could be:

main script                                                  web worker
var myWorker = new Worker('worker.js');
myWorker.onmessage = function(evt) {..};
myWorker.postMessage('start');
                                                                  onmessage
= function(evt) { .. }
//..

And then the message from the main script is never received by the web
worker and it won't start its work.

Could that happen? From what you have said, I think it could.

Tobias
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/help-whatwg.org/attachments/20100803/e0eca1ac/attachment-0003.htm>


More information about the Help mailing list