Bug 965309 - Shut down the sync loop, if any, when we shut down the XHR. r=bent, a=lsblakk
authorKyle Huey <khuey@kylehuey.com>
Wed, 28 May 2014 22:07:38 -0700
changeset 192415 99c91ade2a45378b08b7cb5f2d2eb1d31d9f95a7
parent 192414 f2a2af61e05db88d9281debc71782a5fad5ca7f6
child 192416 f24c36fc3a763764f3507168495bcc8d1bb0fed3
push id3610
push userryanvm@gmail.com
push dateThu, 29 May 2014 17:14:25 +0000
treeherdermozilla-beta@99c91ade2a45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent, lsblakk
bugs965309
milestone30.0
Bug 965309 - Shut down the sync loop, if any, when we shut down the XHR. r=bent, a=lsblakk
dom/workers/XMLHttpRequest.cpp
dom/workers/test/mochitest.ini
dom/workers/test/terminateSyncXHR_frame.html
dom/workers/test/terminateSyncXHR_worker.js
dom/workers/test/test_terminateSyncXHR.html
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -560,16 +560,17 @@ public:
 private:
   ~SyncTeardownRunnable()
   { }
 
   virtual nsresult
   MainThreadRun() MOZ_OVERRIDE
   {
     mProxy->Teardown();
+    MOZ_ASSERT(!mProxy->mSyncLoopTarget);
     return NS_OK;
   }
 };
 
 class SetBackgroundRequestRunnable MOZ_FINAL :
   public WorkerThreadProxySyncRunnable
 {
   bool mValue;
@@ -949,24 +950,37 @@ Proxy::Teardown()
 
     if (mOutstandingSendCount) {
       nsRefPtr<XHRUnpinRunnable> runnable =
         new XHRUnpinRunnable(mWorkerPrivate, mXMLHttpRequestPrivate);
       if (!runnable->Dispatch(nullptr)) {
         NS_RUNTIMEABORT("We're going to hang at shutdown anyways.");
       }
 
+      if (mSyncLoopTarget) {
+        // We have an unclosed sync loop.  Fix that now.
+        nsRefPtr<MainThreadStopSyncLoopRunnable> runnable =
+          new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
+                                             mSyncLoopTarget.forget(),
+                                             false);
+        if (!runnable->Dispatch(nullptr)) {
+          NS_RUNTIMEABORT("We're going to hang at shutdown anyways.");
+        }
+      }
+
       mWorkerPrivate = nullptr;
-      mSyncLoopTarget = nullptr;
       mOutstandingSendCount = 0;
     }
 
     mXHRUpload = nullptr;
     mXHR = nullptr;
   }
+
+  MOZ_ASSERT(!mWorkerPrivate);
+  MOZ_ASSERT(!mSyncLoopTarget);
 }
 
 bool
 Proxy::AddRemoveEventListeners(bool aUpload, bool aAdd)
 {
   AssertIsOnMainThread();
 
   NS_ASSERTION(!aUpload ||
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -41,16 +41,18 @@ support-files =
   relativeLoad_worker.js
   relativeLoad_worker2.js
   rvals_worker.js
   sharedWorker_sharedWorker.js
   simpleThread_worker.js
   suspend_iframe.html
   suspend_worker.js
   terminate_worker.js
+  terminateSyncXHR_frame.html
+  terminateSyncXHR_worker.js
   testXHR.txt
   threadErrors_worker1.js
   threadErrors_worker2.js
   threadErrors_worker3.js
   threadErrors_worker4.js
   threadTimeouts_worker.js
   throwingOnerror_worker.js
   timeoutTracing_worker.js
@@ -119,16 +121,17 @@ skip-if = buildapp == 'b2g' # b2g(Failed
 [test_resolveWorker-assignment.html]
 [test_resolveWorker.html]
 [test_rvals.html]
 [test_sharedWorker.html]
 [test_simpleThread.html]
 [test_suspend.html]
 skip-if = buildapp == 'b2g' || e10s # b2g(test timed out, might need more time) b2g-debug(test timed out, might need more time) b2g-desktop(test timed out, might need more time)
 [test_terminate.html]
+[test_terminateSyncXHR.html]
 [test_threadErrors.html]
 [test_threadTimeouts.html]
 [test_throwingOnerror.html]
 [test_timeoutTracing.html]
 [test_transferable.html]
 [test_url.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only crash, bug 931887
 [test_urlApi.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/terminateSyncXHR_frame.html
@@ -0,0 +1,25 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <title>Test for SharedWorker</title>
+  </head>
+  <body>
+    <script type="text/javascript">
+      function doStuff() {
+        var worker = new Worker("terminateSyncXHR_worker.js");
+
+        worker.onmessage = function(event) {
+          parent.postMessage(event.data, "*");
+        };
+
+        worker.onerror = function(event) {
+          parent.postMessage("ERROR!", "*");
+        }
+      }
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/terminateSyncXHR_worker.js
@@ -0,0 +1,19 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+onmessage = function(event) {
+  throw "No messages should reach me!";
+}
+
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "testXHR.txt", false);
+xhr.addEventListener("loadstart", function ()
+{
+  // Tell the parent to terminate us.
+  postMessage("TERMINATE");
+  // And wait for it to do so.
+  while(1) { true; }
+});
+xhr.send(null);
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_terminateSyncXHR.html
@@ -0,0 +1,45 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+  <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content">
+  <iframe id="iframe" src="terminateSyncXHR_frame.html"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+  var ifr = document.getElementById("iframe");
+
+  window.onmessage = function(event) {
+    if (event.data == "TERMINATE") {
+      ok(true, "Got TERMINATE");
+      ifr.parentNode.removeChild(ifr);
+      SimpleTest.finish();
+    } else {
+      ok(false, "Unexpected message: " + event.data);
+    }
+  }
+
+  SimpleTest.waitForExplicitFinish();
+
+  window.onload = function() {
+    ifr.contentWindow.doStuff();
+  }
+
+</script>
+</pre>
+</body>
+</html>
+