Bug 1526891 - Part 13: Send an async IPC message instead of dispatching a runnable to the PBackground thread when shutting down quota manager; r=asuth
authorJan Varga <jan.varga@gmail.com>
Sat, 23 Feb 2019 17:30:41 +0100
changeset 520826 992bfd5a7b28e5ef2709bb32eb7c464c8c580a1c
parent 520825 3aea75627220e61d802e4af99bd790ebc1a1d6a1
child 520827 830813029a78357c3d45378e4af6be4e68508704
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1526891
milestone67.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 1526891 - Part 13: Send an async IPC message instead of dispatching a runnable to the PBackground thread when shutting down quota manager; r=asuth Differential Revision: https://phabricator.services.mozilla.com/D20922
dom/quota/ActorsParent.cpp
dom/quota/ActorsParent.h
dom/quota/QuotaManager.h
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -38,18 +38,20 @@
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/localstorage/ActorsParent.h"
 #include "mozilla/dom/quota/PQuotaParent.h"
 #include "mozilla/dom/quota/PQuotaRequestParent.h"
 #include "mozilla/dom/quota/PQuotaUsageRequestParent.h"
 #include "mozilla/dom/simpledb/ActorsParent.h"
 #include "mozilla/dom/StorageActivityService.h"
 #include "mozilla/dom/StorageDBUpdater.h"
+#include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/BackgroundUtils.h"
+#include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/net/MozURL.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextUtils.h"
 #include "mozilla/Telemetry.h"
@@ -460,46 +462,31 @@ class QuotaManager::CreateRunnable final
 
   void CallCallbacks();
 
   State GetNextState(nsCOMPtr<nsIEventTarget>& aThread);
 
   NS_DECL_NSIRUNNABLE
 };
 
-class QuotaManager::ShutdownRunnable final : public Runnable {
-  // Only touched on the main thread.
-  bool& mDone;
-
- public:
-  explicit ShutdownRunnable(bool& aDone)
-      : Runnable("dom::quota::QuotaManager::ShutdownRunnable"), mDone(aDone) {
-    MOZ_ASSERT(NS_IsMainThread());
-  }
-
- private:
-  ~ShutdownRunnable() {}
-
-  NS_DECL_NSIRUNNABLE
-};
-
 class QuotaManager::Observer final : public nsIObserver {
   static Observer* sInstance;
 
-  nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
   bool mPendingProfileChange;
+  bool mShutdownComplete;
 
  public:
   static nsresult Initialize();
 
-  static nsresult SetBackgroundEventTarget(
-      nsIEventTarget* aBackgroundEventTarget);
+  static void ShutdownCompleted();
 
  private:
-  Observer() : mPendingProfileChange(false) { MOZ_ASSERT(NS_IsMainThread()); }
+  Observer() : mPendingProfileChange(false), mShutdownComplete(false) {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
 
   ~Observer() { MOZ_ASSERT(NS_IsMainThread()); }
 
   nsresult Init();
 
   nsresult Shutdown();
 
   NS_DECL_ISUPPORTS
@@ -2215,16 +2202,24 @@ PQuotaParent* AllocPQuotaParent() {
 bool DeallocPQuotaParent(PQuotaParent* aActor) {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   RefPtr<Quota> actor = dont_AddRef(static_cast<Quota*>(aActor));
   return true;
 }
 
+bool RecvShutdownQuotaManager() {
+  AssertIsOnBackgroundThread();
+
+  QuotaManager::ShutdownInstance();
+
+  return true;
+}
+
 /*******************************************************************************
  * Directory lock
  ******************************************************************************/
 
 DirectoryLockImpl::DirectoryLockImpl(
     QuotaManager* aQuotaManager,
     const Nullable<PersistenceType>& aPersistenceType, const nsACString& aGroup,
     const OriginScope& aOriginScope, const Nullable<Client::Type>& aClientType,
@@ -2334,20 +2329,17 @@ nsresult QuotaManager::CreateRunnable::I
 
   return NS_OK;
 }
 
 nsresult QuotaManager::CreateRunnable::RegisterObserver() {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mState == State::RegisteringObserver);
 
-  nsresult rv = Observer::SetBackgroundEventTarget(mOwningThread);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
+  nsresult rv;
 
   // This service has to be started on the main thread currently.
   nsCOMPtr<mozIStorageService> ss =
       do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -2434,38 +2426,16 @@ QuotaManager::CreateRunnable::Run() {
 
   if (thread) {
     MOZ_ALWAYS_SUCCEEDS(thread->Dispatch(this, NS_DISPATCH_NORMAL));
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-QuotaManager::ShutdownRunnable::Run() {
-  if (NS_IsMainThread()) {
-    mDone = true;
-
-    return NS_OK;
-  }
-
-  AssertIsOnBackgroundThread();
-
-  RefPtr<QuotaManager> quotaManager = gInstance.get();
-  if (quotaManager) {
-    quotaManager->Shutdown();
-
-    gInstance = nullptr;
-  }
-
-  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
-
-  return NS_OK;
-}
-
 QuotaManager::Observer* QuotaManager::Observer::sInstance = nullptr;
 
 // static
 nsresult QuotaManager::Observer::Initialize() {
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<Observer> observer = new Observer();
 
@@ -2475,24 +2445,21 @@ nsresult QuotaManager::Observer::Initial
   }
 
   sInstance = observer;
 
   return NS_OK;
 }
 
 // static
-nsresult QuotaManager::Observer::SetBackgroundEventTarget(
-    nsIEventTarget* aBackgroundEventTarget) {
+void QuotaManager::Observer::ShutdownCompleted() {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(sInstance);
 
-  sInstance->mBackgroundEventTarget = aBackgroundEventTarget;
-
-  return NS_OK;
+  sInstance->mShutdownComplete = true;
 }
 
 nsresult QuotaManager::Observer::Init() {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (NS_WARN_IF(!obs)) {
     return NS_ERROR_FAILURE;
@@ -2568,35 +2535,38 @@ QuotaManager::Observer::Observe(nsISuppo
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     return NS_OK;
   }
 
   if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID)) {
-    // mBackgroundThread can be null if we somehow get here without
-    // receiving SetBackgroundEventTarget() first.  mPendingProfileChange is our
-    // re-entrancy guard (the nested event loop below may cause re-entrancy).
-    if (!mBackgroundEventTarget || mPendingProfileChange) {
+    // mPendingProfileChange is our re-entrancy guard (the nested event loop
+    // below may cause re-entrancy).
+    if (mPendingProfileChange) {
       return NS_OK;
     }
 
     AutoRestore<bool> pending(mPendingProfileChange);
     mPendingProfileChange = true;
 
-    MOZ_ASSERT(gInstance);
-
-    bool done = false;
-
-    RefPtr<ShutdownRunnable> shutdownRunnable = new ShutdownRunnable(done);
-    MOZ_ALWAYS_SUCCEEDS(
-        mBackgroundEventTarget->Dispatch(shutdownRunnable, NS_DISPATCH_NORMAL));
-
-    MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return done; }));
+    mShutdownComplete = false;
+
+    PBackgroundChild* backgroundActor =
+        BackgroundChild::GetOrCreateForCurrentThread();
+    if (NS_WARN_IF(!backgroundActor)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    if (NS_WARN_IF(!backgroundActor->SendShutdownQuotaManager())) {
+      return NS_ERROR_FAILURE;
+    }
+
+    MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return mShutdownComplete; }));
 
     gBaseDirPath.Truncate();
 
     return NS_OK;
   }
 
   if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     rv = Shutdown();
@@ -2980,16 +2950,34 @@ QuotaManager* QuotaManager::Get() {
   // Does not return an owning reference.
   return gInstance;
 }
 
 // static
 bool QuotaManager::IsShuttingDown() { return gShutdown; }
 
 // static
+void QuotaManager::ShutdownInstance() {
+  AssertIsOnBackgroundThread();
+
+  if (gInstance) {
+    gInstance->Shutdown();
+
+    gInstance = nullptr;
+  }
+
+  RefPtr<Runnable> runnable =
+      NS_NewRunnableFunction("dom::quota::QuotaManager::ShutdownCompleted",
+                             []() { Observer::ShutdownCompleted(); });
+  MOZ_ASSERT(runnable);
+
+  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable.forget()));
+}
+
+// static
 bool QuotaManager::IsOSMetadata(const nsAString& aFileName) {
   return aFileName.EqualsLiteral(DSSTORE_FILE_NAME) ||
          aFileName.EqualsLiteral(DESKTOP_FILE_NAME) ||
          aFileName.LowerCaseEqualsLiteral(DESKTOP_INI_FILE_NAME) ||
          aFileName.EqualsLiteral(THUMBS_DB_FILE_NAME);
 }
 
 // static
--- a/dom/quota/ActorsParent.h
+++ b/dom/quota/ActorsParent.h
@@ -14,13 +14,15 @@ namespace quota {
 class PQuotaParent;
 
 void InitializeQuotaManager();
 
 PQuotaParent* AllocPQuotaParent();
 
 bool DeallocPQuotaParent(PQuotaParent* aActor);
 
+bool RecvShutdownQuotaManager();
+
 }  // namespace quota
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_quota_ActorsParent_h
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -94,17 +94,16 @@ class QuotaManager final : public Backgr
   typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
   typedef nsClassHashtable<nsCStringHashKey, nsTArray<DirectoryLockImpl*>>
       DirectoryLockTable;
 
  public:
   class CreateRunnable;
 
  private:
-  class ShutdownRunnable;
   class Observer;
 
  public:
   NS_INLINE_DECL_REFCOUNTING(QuotaManager)
 
   static nsresult Initialize();
 
   static bool IsRunningXPCShellTests() {
@@ -124,16 +123,18 @@ class QuotaManager final : public Backgr
                           nsIEventTarget* aMainEventTarget = nullptr);
 
   // Returns a non-owning reference.
   static QuotaManager* Get();
 
   // Returns true if we've begun the shutdown process.
   static bool IsShuttingDown();
 
+  static void ShutdownInstance();
+
   static bool IsOSMetadata(const nsAString& aFileName);
 
   static bool IsDotFile(const nsAString& aFileName);
 
   bool IsOriginInitialized(const nsACString& aOrigin) const {
     AssertIsOnIOThread();
 
     return mInitializedOrigins.Contains(aOrigin);
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -979,16 +979,30 @@ BackgroundParentImpl::PQuotaParent* Back
 bool BackgroundParentImpl::DeallocPQuotaParent(PQuotaParent* aActor) {
   AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::quota::DeallocPQuotaParent(aActor);
 }
 
+mozilla::ipc::IPCResult BackgroundParentImpl::RecvShutdownQuotaManager() {
+  AssertIsInMainOrSocketProcess();
+  AssertIsOnBackgroundThread();
+
+  if (BackgroundParent::IsOtherProcessActor(this)) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  if (!mozilla::dom::quota::RecvShutdownQuotaManager()) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+  return IPC_OK();
+}
+
 dom::PFileSystemRequestParent*
 BackgroundParentImpl::AllocPFileSystemRequestParent(
     const FileSystemParams& aParams) {
   AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<FileSystemRequestParent> result = new FileSystemRequestParent();
 
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -270,16 +270,18 @@ class BackgroundParentImpl : public PBac
 
   virtual bool DeallocPAsmJSCacheEntryParent(
       PAsmJSCacheEntryParent* aActor) override;
 
   virtual PQuotaParent* AllocPQuotaParent() override;
 
   virtual bool DeallocPQuotaParent(PQuotaParent* aActor) override;
 
+  virtual mozilla::ipc::IPCResult RecvShutdownQuotaManager() override;
+
   virtual PFileSystemRequestParent* AllocPFileSystemRequestParent(
       const FileSystemParams&) override;
 
   virtual mozilla::ipc::IPCResult RecvPFileSystemRequestConstructor(
       PFileSystemRequestParent* actor, const FileSystemParams& params) override;
 
   virtual bool DeallocPFileSystemRequestParent(
       PFileSystemRequestParent*) override;
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -186,16 +186,18 @@ parent:
   async MessagePortForceClose(nsID uuid, nsID destinationUuid, uint32_t sequenceId);
 
   async PAsmJSCacheEntry(OpenMode openMode,
                          WriteParams write,
                          PrincipalInfo principalInfo);
 
   async PQuota();
 
+  async ShutdownQuotaManager();
+
   async PFileSystemRequest(FileSystemParams params);
 
   async PGamepadEventChannel();
 
   async PGamepadTestChannel();
 
   async PHttpBackgroundChannel(uint64_t channelId);