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

Drew Wilson atwilson at chromium.org
Tue Aug 3 14:09:52 PDT 2010


On Tue, Aug 3, 2010 at 1:40 PM, Rik Sagar <org.whatwg at sagar.org> wrote:

>
> I would expect in this example that the *Worker got loaded*  message
> should be dropped on the floor.
>
> I would expect exactly the opposite - that message should be delivered.

Here's the way I look at worker messaging (and events in general) - each
javascript context (or "thread" if you will) has what amounts to an event
loop. When your javascript code returns from an event handler (or, in the
case of worker script, returns from an event handler or returns from
executing the initial block of script), you drop back in to your event loop
and start dispatching events.

There are a number of things that can generate events (that can be "event
sources") - for example, a timer is an event source. MessagePorts (both
explicit MessagePorts and also implicit ones for Dedicated Workers) are
event sources, too. When you queue up an event for a MessagePort, it becomes
an active event source (meaning that when the associated javascript context
re-enters its event loop, that MessagePort can cause an onmessage event to
be generated). The event loop traverses the various associated event sources
for the javascript context (timers, message ports, etc) and fires off an
event from one of the event sources (the spec doesn't specify an ordering
here, so it's up to the UA to decide how to prioritize various event
sources) - when it fires off the event, any handlers associated with that
event will receive the event, and if there are no handlers the typical
default handling of the event occurs (gets dropped on the floor, or maybe
gets bubbled up in the case of DOM events, etc).

So, in your case above, here's what happens - webapp_main creates a worker
and then adds an "onmessage" handler to the worker object. Now,
webapp_worker runs, sets up an onmessage handler (which, btw, will never be
executed since you never send any messages to the worker in your example),
then fires off a "Worker got loaded" message to webapp_main. Even if this
code is executed before webapp_main has set its onmessage handler, the event
will not get dropped on the floor - remember that all postMessage() does is
put the event in the MessagePort's queue, then make that MessagePort an
active event source. So as long as webapp_main sets an onmessage handler
before it returns back to the event loop, there's no way for the event to
get dropped on the floor because the event isn't even dispatched until you
get back to the event loop.

Hopefully this helps clear up some of the confusion - it's important to
understand that the various flavors of postMessage() are entirely
asynchronous and rely on events being dispatched from the event loop.



> Thanks,
> Rik.
>
>
>
>
> Rik Sagar, San Jose, CA 95124
> Visit : http://sagar.org/
>
>
>
> On Mon, Aug 2, 2010 at 10:09 AM, 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
>>
>>
>> _______________________________________________
>> Help mailing list
>> Help at lists.whatwg.org
>> http://lists.whatwg.org/listinfo.cgi/help-whatwg.org
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/help-whatwg.org/attachments/20100803/f3c1d8ae/attachment-0003.htm>


More information about the Help mailing list