Bug 1396652: Ensure ordered destruction of channel entries at shutdown. r=mixedpuppy
authorKris Maglione <maglione.k@gmail.com>
Mon, 04 Sep 2017 14:31:26 -0700
changeset 428449 cdecd701b70f219f9d60731418ce20eb0d3761fd
parent 428368 fcb0997350fdf472f6ec3546e7767e11f4784cc1
child 428450 7208ebbc9162b8444f7543cde4d898e144a05933
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy
bugs1396652
milestone57.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 1396652: Ensure ordered destruction of channel entries at shutdown. r=mixedpuppy When channel registrations aren't explicitly unregistred from JS, they're instead unregistered when the entry object is cycle collected. When the entries are created close to shutdown, that can leave some uncertainty as to the order of destruction, and the WebRequestService might wind up being destroyed before all of the entries. In that case, the registrations are cleaned up when the hash entries hash table is being destroyed. While that isn't strictly a problem, the entries expect to still be present in the hash table when they're being destroyed, as a basic sanity check. This patch ensures that we always remove entries from the hash table before it's destroyed, so those invariants are maintained. MozReview-Commit-ID: 5jWpFeFyjJZ
toolkit/components/extensions/webrequest/WebRequestService.cpp
toolkit/components/extensions/webrequest/WebRequestService.h
--- a/toolkit/components/extensions/webrequest/WebRequestService.cpp
+++ b/toolkit/components/extensions/webrequest/WebRequestService.cpp
@@ -22,16 +22,20 @@ using namespace mozilla::dom;
 
 WebRequestService::WebRequestService()
   : mDataLock("WebRequest service data lock")
 {
 }
 
 WebRequestService::~WebRequestService()
 {
+  for (auto iter = mChannelEntries.Iter(); !iter.Done(); iter.Next()) {
+    auto& channel = iter.Data();
+    channel->DetachAll();
+  }
 }
 
 NS_IMPL_ISUPPORTS(WebRequestService, mozIWebRequestService)
 
 /* static */ WebRequestService&
 WebRequestService::GetSingleton()
 {
   static RefPtr<WebRequestService> instance;
@@ -127,17 +131,18 @@ WebRequestService::ChannelParent::Detach
 
   removeFrom(entry->mTabParents);
   if (entry->mTabParents.isEmpty()) {
     map.Remove(mChannelId);
   }
   mDetached = true;
 }
 
-WebRequestService::ChannelEntry::~ChannelEntry()
+void
+WebRequestService::ChannelEntry::DetachAll()
 {
   while (ChannelParent* parent = mTabParents.getFirst()) {
     parent->Detach();
   }
 }
 
 WebRequestService::Destructor::~Destructor()
 {
--- a/toolkit/components/extensions/webrequest/WebRequestService.h
+++ b/toolkit/components/extensions/webrequest/WebRequestService.h
@@ -83,17 +83,18 @@ private:
   private:
     ChannelParent* mChannelParent;
     bool mDestructCalled;
   };
 
   class ChannelEntry
   {
   public:
-    ~ChannelEntry();
+    void DetachAll();
+
     // Note: We can't keep a strong pointer to the channel here, since channels
     // are not cycle collected, and a reference to this object will be stored on
     // the channel in order to keep the entry alive.
     nsWeakPtr mChannel;
     LinkedList<ChannelParent> mTabParents;
   };
 
   nsClassHashtable<nsUint64HashKey, ChannelEntry> mChannelEntries;