Bug 1396652: Fix WebRequestService destructor ordering issue. r?mixedpuppy draft
authorKris Maglione <maglione.k@gmail.com>
Thu, 07 Sep 2017 19:04:01 -0700
changeset 661175 4238fc77e76886bffc08f9e0ff56fa77aaf0910c
parent 661153 604fd3302562dc2059a8de3231818a1b618b8ffe
child 661508 8b593855f739c6423c1c22dc177653e0b837ed23
push id78661
push usermaglione.k@gmail.com
push dateFri, 08 Sep 2017 04:00:48 +0000
reviewersmixedpuppy
bugs1396652
milestone57.0a1
Bug 1396652: Fix WebRequestService destructor ordering issue. r?mixedpuppy MozReview-Commit-ID: HYDNYzb5bnM
toolkit/components/extensions/webrequest/WebRequestService.cpp
--- a/toolkit/components/extensions/webrequest/WebRequestService.cpp
+++ b/toolkit/components/extensions/webrequest/WebRequestService.cpp
@@ -9,46 +9,62 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "nsCOMPtr.h"
 #include "nsIChannel.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsISupports.h"
 #include "nsITabParent.h"
 #include "nsITraceableChannel.h"
+#include "nsTArray.h"
 
 #include "mozilla/dom/TabParent.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+static WebRequestService* sWeakWebRequestService;
+
 WebRequestService::WebRequestService()
   : mDataLock("WebRequest service data lock")
 {
 }
 
 WebRequestService::~WebRequestService()
 {
+  // Store existing entries in an array, since Detach can't safely remove them
+  // while we're iterating the hashtable.
+  AutoTArray<ChannelEntry*, 32> entries;
   for (auto iter = mChannelEntries.Iter(); !iter.Done(); iter.Next()) {
-    auto& channel = iter.Data();
+    entries.AppendElement(iter.Data());
+  }
+
+  for (auto channel : entries) {
     channel->DetachAll();
   }
+
+  sWeakWebRequestService = nullptr;
 }
 
 NS_IMPL_ISUPPORTS(WebRequestService, mozIWebRequestService)
 
 /* static */ WebRequestService&
 WebRequestService::GetSingleton()
 {
   static RefPtr<WebRequestService> instance;
-  if (!instance) {
+  if (!sWeakWebRequestService) {
     instance = new WebRequestService();
     ClearOnShutdown(&instance);
+
+    // A separate weak instance that we keep a reference to as long as the
+    // original service is alive, even after our strong reference is cleared to
+    // allow the service to be destroyed.
+    sWeakWebRequestService = instance;
   }
-  return *instance;
+  return *sWeakWebRequestService;
 }
 
 
 NS_IMETHODIMP
 WebRequestService::RegisterTraceableChannel(uint64_t aChannelId,
                                             nsIChannel* aChannel,
                                             const nsAString& aAddonId,
                                             nsITabParent* aTabParent,