Bug 941787 - Fix race between tab closure event and nested event loop popping in devtools browser actor. r=panos, a=lsblakk
authorShu-yu Guo <shu@rfrn.org>
Sun, 24 Nov 2013 22:51:19 -0800
changeset 161162 b189801a4cc41d93b084f442a96246f7d2275fb3
parent 161161 11a6c2c6af79155d4c4d453e1a152a7e35ee9a14
child 161163 7b9a3ac04ebb8b9b27f388e40e9eb7213b90632f
push id3051
push userryanvm@gmail.com
push dateWed, 27 Nov 2013 03:45:09 +0000
treeherdermozilla-beta@b189801a4cc4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspanos, lsblakk
bugs941787
milestone26.0
Bug 941787 - Fix race between tab closure event and nested event loop popping in devtools browser actor. r=panos, a=lsblakk
toolkit/devtools/server/actors/webbrowser.js
--- a/toolkit/devtools/server/actors/webbrowser.js
+++ b/toolkit/devtools/server/actors/webbrowser.js
@@ -465,16 +465,19 @@ function BrowserTabActor(aConnection, aB
   this.conn = aConnection;
   this._browser = aBrowser;
   this._tabbrowser = aTabBrowser;
   this._tabActorPool = null;
   // A map of actor names to actor instances provided by extensions.
   this._extraActors = {};
 
   this._onWindowCreated = this.onWindowCreated.bind(this);
+
+  // Number of event loops nested.
+  this._nestedEventLoopDepth = 0;
 }
 
 // XXX (bug 710213): BrowserTabActor attach/detach/exit/disconnect is a
 // *complete* mess, needs to be rethought asap.
 
 BrowserTabActor.prototype = {
   get browser() { return this._browser; },
 
@@ -613,16 +616,19 @@ BrowserTabActor.prototype = {
     }
 
     if (this.attached) {
       this._detach();
       this.conn.send({ from: this.actorID,
                        type: "tabDetached" });
     }
 
+    // Pop all nested event loops if we haven't already.
+    while (this._nestedEventLoopDepth > 0)
+      this.postNest();
     this._browser = null;
     this._tabbrowser = null;
   },
 
   /* Support for DebuggerServer.addTabActor. */
   _createExtraActors: CommonCreateExtraActors,
   _appendExtraActors: CommonAppendExtraActors,
 
@@ -761,35 +767,39 @@ BrowserTabActor.prototype = {
       // The tab is already closed.
       return;
     }
     let windowUtils = this.window
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDOMWindowUtils);
     windowUtils.suppressEventHandling(true);
     windowUtils.suspendTimeouts();
+    this._nestedEventLoopDepth++;
   },
 
   /**
    * Prepare to exit a nested event loop by enabling debuggee events.
    */
   postNest: function BTA_postNest(aNestData) {
     if (!this.window) {
       // The tab is already closed.
+      dbg_assert(this._nestedEventLoopDepth === 0,
+                 "window shouldn't be closed before all nested event loops have been popped");
       return;
     }
     let windowUtils = this.window
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDOMWindowUtils);
     windowUtils.resumeTimeouts();
     windowUtils.suppressEventHandling(false);
     if (this._pendingNavigation) {
       this._pendingNavigation.resume();
       this._pendingNavigation = null;
     }
+    this._nestedEventLoopDepth--;
   },
 
   /**
    * Handle location changes, by clearing the previous debuggees and enabling
    * debugging, which may have been disabled temporarily by the
    * DebuggerProgressListener.
    */
   onWindowCreated: