Are Firefox worker threads worthless?

February 8, 2009
By Mike

It was with some excitement that I recently learned about worker thread support in Firefox 3.1. For many years I have whined about JavaScript’s inability to spawn threads, so when I heard the news I immediately started thinking about moving all of the resource hogging code of Wizz RSS into worker threads.

A few days ago I started moving the Import Public List code into a worker. This probably isn’t the most important part of the code to move into a worker, but I thought it would be a good place to start. A fairly simple part of the Wizz RSS code that would gently introduce me to the new worker thread functionality in Firefox 3.1.

Hmmmm… Not long into the exercise and I started to hit problems :(

The Import Public List code makes extensive use of PlacesUIUtils to create folders, bookmarks and annotations. After hours of struggling to find a way to get the worker to reference PlacesUIUtils, all I achieved was a worker thread that would effectively lock up the browser and never let it go! Back to the drawing board!

I then decided to rewrite all of the PlacesUIUtils calls and replace them with calls to nsINavBookmarksService. Success! Well almost!

The worker thread worked, but I kept getting the following error message dumped to the console: -

[JavaScript Error: "uncaught exception: [Exception... "Component returned
failure code: 0x8000ffff (NS_ERROR_UNEXPECTED)
[nsIObserverService.notifyObservers]” nsresult: “0x8000ffff
(NS_ERROR_UNEXPECTED)” location: “JS frame ::
file:///C:/Program%20Files/Mozilla%20Firefox%203.1%20Beta%202/components/nsPlacesDBFlush.js
:: DBFlush_handleCompletion :: line 198″ data: no]”]

What’s more, after running the code a few times, Firefox would abend!

Hmmmmm (Again)… Not good! So I decided to wrap all of the nsINavBookmarksService calls inside a transaction by using nsINavBookmarksService.runInBatchMode. The number of errors dumped to the console reduced from around 10 to around 3, but still, occasionally, Firefox would abend.

I tried wrapping line 198 of nsPlacesDBFlush.js inside a try catch. I wasn’t really expecting this to work, but anything was worth a try. As expected, the try catch stopped the errors being dumped to the console, but it didn’t stop Firefox abending.

After spending almost 3 days hacking around and trying different things, like trying to get the worker thread to use postMessage to pass folder and bookmark information back to the parent thread, so that the parent thread could make the nsINavBookmarksService calls (Information passed back to the parent thread in this way, for some weird reason, gets inverted. i.e. The first postMessage gets to the parent last, while the last postMessage gets to the parent first… Huh?), I gave up and decided to log a bug.

Much to my surprise my bug was flagged RESOLVED/INVALID, and it received the following comment from Shawn Wilsher: -

You can’t use arbitrary components on different threads. These services are
not threadsafe!

Hmmmmm (For a third time)… So what then is the point of worker threads? I guess this makes them pretty worthless to most extension developers!

9 Responses to Are Firefox worker threads worthless?

  1. Christopher Blizzard on February 9, 2009 at 1:25 am

    It’s true that most of worker threads has content in mind, not extensions. Most of the ways that you can pass data in and out of a thread in content and the fact that you can’t access the DOM directly are like that because of what you ran into – accessing and modifying some data from multiple threads is dangerous!

    There have been threading primitives available to extensions for quite a while, but neither workers nor the previous interfaces mean that you can make arbitrary calls from arbitrary threads at will. Nothing has changed here. Threaded programming is very different than “normal” programming with a single thread. It’s possible to do a lot of damage.

    Being able to do whatever you want from any thread is basically impossible. Our codebase doesn’t support that nor will it. (Nor does anyone else’s, really!)

    I know this isn’t the answer that you were looking for and I’m sorry that we failed to set expectations properly. But threading from extensions is just like threading in any program – full of danger. We’ll add some verbage about that in the pages.

  2. Christopher Blizzard on February 10, 2009 at 12:00 am

    By the way, we updated the docs to reflect reality:

    https://developer.mozilla.org/En/Using_DOM_workers#About_thread_safety

    Thanks for posting about this. It pointed out an assumption we weren’t taking into account.

  3. Mike on February 10, 2009 at 7:18 am

    Thanks Christopher!

    Unfortunately that still leaves me (And probably many others) wanting/needing to spawn threads, but not being able to :(

  4. Christopher Blizzard on February 10, 2009 at 7:25 am

    I certainly understand your frustration. I’ve done my own share of threaded programming and it’s not an easy task. Sadly there just aren’t easy answers to the questions of concurrency. There are very few large frameworks where everything is threadsafe. (Java Swing is the only one that comes to mind, actually.)

    Our threads are useful in a lot of cases, but it doesn’t sound like it’s appropriate to solve the problem that you’re having.

  5. Michael Leuchtenburg on February 24, 2009 at 10:46 pm

    You might try using the usual mechanisms for wrapping a thread-unsafe component: apply a lock to all calls to the nsINavBookmarksService so that only one thread will write to it at once. Of course, you may still be screwed if the main thread is also using that service in a way you can’t wrap such that it uses the lock. In that case, you’ll need to have some code running in the main thread and do all bookmark updates there.

  6. Mike on February 24, 2009 at 10:51 pm

    Ah-ha! Thanks Michael! That sounds like something worth investigating :)

  7. Calain on July 7, 2009 at 11:00 am

    I’m very sorry to read this.

    I love this extension but every time it fetches the RSS feeds “in the background” the whole browser freezes.

    I was really exited about when I heard about the worker threads, as I hoped the worker threads would help to eliminate this. For me that would be he perfect use for such threads.

    I wanted to wait until FF3.5 was released to check if you would make the change on your own (as you tried). Now after reading this I’m disappointed that FF does still not really support it.

    If you still try to get it working with a self written lock mechanism, let me know. I am not deeply into extension programming, but I had several projects, where I could not use build in mechanisms for thread synchronizing. I would be pleased if I could help you getting the threads to work with Wizz RSS.

  8. Mike on July 8, 2009 at 5:23 pm

    @Calain: I haven’t given up on the threading thing… Yet! :)

    Try cleaning out your Watch List cache. Click the red X button on the Found Items tab. This usually causes quite a dramatic improvement in the performance of the Watch List, but of course it isn’t the ideal fix.

  9. andy on July 22, 2009 at 4:50 pm

    Was just trying to initialise java in either a worker thread OR a nsIThreadManager thread (since it locks up the browser when starting normally). Neither works. Worker threads can’t access it, and nsIThreads kill the browser when you try! YAY!

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*