Bug 1445475 - Make service worker self-update fallibly store its timer on the private and cleanup if that fails. r=catalinb, a=jcristau
authorBen Kelly <ben@wanderview.com>
Thu, 22 Mar 2018 07:45:00 -0400
changeset 460393 a93e20c50c4b3d7662cc3170e2683bb8db295fb6
parent 460392 a47898b26ba9c047abd61fec864b2d16c7496c7c
child 460394 3ae35e4029264fb326c45042b06948f9fed3a2e2
push id8929
push userryanvm@gmail.com
push dateTue, 27 Mar 2018 18:55:27 +0000
treeherdermozilla-beta@3ae35e402926 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscatalinb, jcristau
bugs1445475
milestone60.0
Bug 1445475 - Make service worker self-update fallibly store its timer on the private and cleanup if that fails. r=catalinb, a=jcristau
dom/serviceworkers/ServiceWorkerPrivate.cpp
dom/serviceworkers/ServiceWorkerPrivate.h
dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
--- a/dom/serviceworkers/ServiceWorkerPrivate.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp
@@ -1947,24 +1947,29 @@ ServiceWorkerPrivate::SpawnWorkerIfNeede
 
   if (aNewWorkerCreated) {
     *aNewWorkerCreated = true;
   }
 
   return NS_OK;
 }
 
-void
-ServiceWorkerPrivate::StoreISupports(nsISupports* aSupports)
+bool
+ServiceWorkerPrivate::MaybeStoreISupports(nsISupports* aSupports)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate);
+
+  if (!mWorkerPrivate) {
+    MOZ_DIAGNOSTIC_ASSERT(mSupportsArray.IsEmpty());
+    return false;
+  }
+
   MOZ_ASSERT(!mSupportsArray.Contains(aSupports));
-
   mSupportsArray.AppendElement(aSupports);
+  return true;
 }
 
 void
 ServiceWorkerPrivate::RemoveISupports(nsISupports* aSupports)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mSupportsArray.RemoveElement(aSupports);
 }
--- a/dom/serviceworkers/ServiceWorkerPrivate.h
+++ b/dom/serviceworkers/ServiceWorkerPrivate.h
@@ -116,18 +116,18 @@ public:
                         const nsAString& aData,
                         const nsAString& aBehavior,
                         const nsAString& aScope);
 
   nsresult
   SendFetchEvent(nsIInterceptedChannel* aChannel, nsILoadGroup* aLoadGroup,
                  const nsAString& aClientId, bool aIsReload);
 
-  void
-  StoreISupports(nsISupports* aSupports);
+  bool
+  MaybeStoreISupports(nsISupports* aSupports);
 
   void
   RemoveISupports(nsISupports* aSupports);
 
   // This will terminate the current running worker thread and drop the
   // workerPrivate reference.
   // Called by ServiceWorkerInfo when [[Clear Registration]] is invoked
   // or whenever the spec mandates that we terminate the worker.
--- a/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
@@ -389,20 +389,26 @@ public:
                                 SystemGroup::EventTargetFor(TaskCategory::Other));
 
       nsCOMPtr<nsITimer> timer = result.unwrapOr(nullptr);
       if (NS_WARN_IF(!timer)) {
         return NS_OK;
       }
 
       mDelayed = true;
+
       // We're storing the timer object on the calling service worker's private.
       // ServiceWorkerPrivate will drop the reference if the worker terminates,
       // which will cancel the timer.
-      worker->WorkerPrivate()->StoreISupports(timer);
+      if (!worker->WorkerPrivate()->MaybeStoreISupports(timer)) {
+        // The worker thread is already shutting down.  Just cancel the timer
+        // and let the update runnable be destroyed.
+        timer->Cancel();
+        return NS_OK;
+      }
 
       return NS_OK;
     }
 
     RefPtr<WorkerThreadUpdateCallback> cb =
       new WorkerThreadUpdateCallback(mPromiseProxy);
     UpdateInternal(principal, mDescriptor.Scope(), cb);
     return NS_OK;