Bug 944859 - osfile_async_worker.js worker is never shut down in the parent process. r=yoric
authorFabrice Desré <fabrice@mozilla.com>
Tue, 03 Dec 2013 09:48:01 -0800
changeset 158605 b843867654c3cd312709d73d8022062700b410d3
parent 158604 2bc8840ad877a93842510ea7f3f40c404a8652bf
child 158606 aa4a0e828711b23ee471a85ca0c3571a215ec5e6
push id25750
push userryanvm@gmail.com
push dateTue, 03 Dec 2013 22:04:21 +0000
treeherdermozilla-central@79d250edda15 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyoric
bugs944859
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 944859 - osfile_async_worker.js worker is never shut down in the parent process. r=yoric
b2g/app/b2g.js
toolkit/components/osfile/modules/osfile_async_front.jsm
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -843,10 +843,13 @@ pref("b2g.neterror.url", "app://system.g
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
 
 // Downloads API
 pref("dom.mozDownloads.enabled", true);
 pref("dom.downloads.max_retention_days", 7);
 
+// Inactivity time in milliseconds after which we shut down the OS.File worker.
+pref("osfile.reset_worker_delay", 5000);
+
 // The URL of the Firefox Accounts auth server backend
 pref("identity.fxaccounts.auth.uri", "https://api-accounts.dev.lcip.org/v1");
--- a/toolkit/components/osfile/modules/osfile_async_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
@@ -22,16 +22,17 @@
 this.EXPORTED_SYMBOLS = ["OS"];
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
 let SharedAll = {};
 Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", SharedAll);
 Cu.import("resource://gre/modules/Deprecated.jsm", this);
+Cu.import("resource://gre/modules/Timer.jsm", this);
 
 // Boilerplate, to simplify the transition to require()
 let LOG = SharedAll.LOG.bind(SharedAll, "Controller");
 let isTypedArray = SharedAll.isTypedArray;
 
 // The constructor for file errors.
 let SysAll = {};
 if (SharedAll.Constants.Win) {
@@ -112,16 +113,36 @@ let Scheduler = {
    */
   shutdown: false,
 
   /**
    * The latest promise returned.
    */
   latestPromise: Promise.resolve("OS.File scheduler hasn't been launched yet"),
 
+  /**
+   * A timer used to automatically shut down the worker after some time.
+   */
+  resetTimer: null,
+
+  restartTimer: function(arg) {
+    let delay;
+    try {
+      delay = Services.prefs.getIntPref("osfile.reset_worker_delay");
+    } catch(e) {
+      // Don't auto-shutdown if we don't have a delay preference set.
+      return;
+    }
+
+    if (this.resetTimer) {
+      clearTimeout(this.resetTimer);
+    }
+    this.resetTimer = setTimeout(File.resetWorker, delay);
+  },
+
   post: function post(...args) {
     if (this.shutdown) {
       LOG("OS.File is not available anymore. The following request has been rejected.", args);
       return Promise.reject(new Error("OS.File has been shut down."));
     }
     if (!worker) {
       // Either the worker has never been created or it has been reset
       worker = new PromiseWorker(
@@ -134,16 +155,22 @@ let Scheduler = {
     this.launched = true;
 
     // By convention, the last argument of any message may be an |options| object.
     let methodArgs = args[1];
     let options = methodArgs ? methodArgs[methodArgs.length - 1] : null;
     let promise = worker.post.apply(worker, args);
     return this.latestPromise = promise.then(
       function onSuccess(data) {
+        // Don't restart the timer when reseting the worker, since that will
+        // lead to an endless "resetWorker()" loop.
+        if (args[0] != "Meta_reset") {
+          Scheduler.restartTimer();
+        }
+
         // Check for duration and return result.
         if (!options) {
           return data.ok;
         }
         // Check for options.outExecutionDuration.
         if (typeof options !== "object" ||
           !("outExecutionDuration" in options)) {
           return data.ok;
@@ -162,16 +189,22 @@ let Scheduler = {
         if (typeof options.outExecutionDuration == "number") {
           options.outExecutionDuration += durationMs;
         } else {
           options.outExecutionDuration = durationMs;
         }
         return data.ok;
       },
       function onError(error) {
+        // Don't restart the timer when reseting the worker, since that will
+        // lead to an endless "resetWorker()" loop.
+        if (args[0] != "Meta_reset") {
+          Scheduler.restartTimer();
+        }
+
         // Decode any serialized error
         if (error instanceof PromiseWorker.WorkerError) {
           throw OS.File.Error.fromMsg(error.data);
         }
         // Extract something meaningful from ErrorEvent
         if (error instanceof ErrorEvent) {
           let message = error.message;
           if (message == "uncaught exception: [object StopIteration]") {