Bug 1526891 - Part 9: Send an async IPC message instead of dispatching a runnable to the PBackground thread when aborting operations for process; r=asuth
authorJan Varga <jan.varga@gmail.com>
Sat, 23 Feb 2019 17:17:21 +0100
changeset 520822 5d0241e1bc0a0a9ac9693e9406633161d6f8b6aa
parent 520821 1213eb6430d9e5a10323be7fec19883a19873823
child 520823 1afb51b4bf31dfe076221a9c45d4eeeffa7c5dfa
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 9: Send an async IPC message instead of dispatching a runnable to the PBackground thread when aborting operations for process; r=asuth Differential Revision: https://phabricator.services.mozilla.com/D20918
dom/quota/ActorsParent.cpp
dom/quota/PQuota.ipdl
dom/quota/QuotaManagerService.cpp
dom/quota/QuotaManagerService.h
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -974,16 +974,19 @@ class Quota final : public PQuotaParent 
   virtual mozilla::ipc::IPCResult RecvPQuotaRequestConstructor(
       PQuotaRequestParent* aActor, const RequestParams& aParams) override;
 
   virtual bool DeallocPQuotaRequestParent(PQuotaRequestParent* aActor) override;
 
   virtual mozilla::ipc::IPCResult RecvStartIdleMaintenance() override;
 
   virtual mozilla::ipc::IPCResult RecvStopIdleMaintenance() override;
+
+  virtual mozilla::ipc::IPCResult RecvAbortOperationsForProcess(
+      const ContentParentId& aContentParentId) override;
 };
 
 class QuotaUsageRequestBase : public NormalOriginOperationBase,
                               public PQuotaUsageRequestParent {
  public:
   // May be overridden by subclasses if they need to perform work on the
   // background thread before being run.
   virtual bool Init(Quota* aQuota);
@@ -2359,23 +2362,16 @@ nsresult QuotaManager::CreateRunnable::R
 
   // 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;
   }
 
-  QuotaManagerService* qms = QuotaManagerService::GetOrCreate();
-  if (NS_WARN_IF(!qms)) {
-    return rv;
-  }
-
-  qms->NoteLiveManager(mManager);
-
   for (RefPtr<Client>& client : mManager->mClients) {
     client->DidInitialize(mManager);
   }
 
   return NS_OK;
 }
 
 void QuotaManager::CreateRunnable::CallCallbacks() {
@@ -2501,21 +2497,16 @@ QuotaManager::ShutdownObserver::Observe(
     return NS_ERROR_FAILURE;
   }
 
   // Unregister ourselves from the observer service first to make sure the
   // nested event loop below will not cause re-entrancy issues.
   Unused << observerService->RemoveObserver(
       this, PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID);
 
-  QuotaManagerService* qms = QuotaManagerService::Get();
-  MOZ_ASSERT(qms);
-
-  qms->NoteShuttingDownManager();
-
   for (RefPtr<Client>& client : gInstance->mClients) {
     client->WillShutdown();
   }
 
   bool done = false;
 
   RefPtr<ShutdownRunnable> shutdownRunnable = new ShutdownRunnable(done);
   MOZ_ALWAYS_SUCCEEDS(
@@ -6764,16 +6755,42 @@ mozilla::ipc::IPCResult Quota::RecvStopI
     return IPC_OK();
   }
 
   quotaManager->StopIdleMaintenance();
 
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult Quota::RecvAbortOperationsForProcess(
+    const ContentParentId& aContentParentId) {
+  AssertIsOnBackgroundThread();
+
+  PBackgroundParent* actor = Manager();
+  MOZ_ASSERT(actor);
+
+  if (BackgroundParent::IsOtherProcessActor(actor)) {
+    ASSERT_UNLESS_FUZZING();
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  if (QuotaManager::IsShuttingDown()) {
+    return IPC_OK();
+  }
+
+  QuotaManager* quotaManager = QuotaManager::Get();
+  if (!quotaManager) {
+    return IPC_OK();
+  }
+
+  quotaManager->AbortOperationsForProcess(aContentParentId);
+
+  return IPC_OK();
+}
+
 bool QuotaUsageRequestBase::Init(Quota* aQuota) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aQuota);
 
   mNeedsQuotaManagerInit = true;
 
   return true;
 }
--- a/dom/quota/PQuota.ipdl
+++ b/dom/quota/PQuota.ipdl
@@ -11,16 +11,19 @@ include PBackgroundSharedTypes;
 include "mozilla/dom/quota/SerializationHelpers.h";
 
 using mozilla::dom::quota::PersistenceType
   from "mozilla/dom/quota/PersistenceType.h";
 
 using mozilla::dom::quota::Client::Type
   from "mozilla/dom/quota/Client.h";
 
+using mozilla::dom::ContentParentId
+  from "mozilla/dom/ipc/IdType.h";
+
 namespace mozilla {
 namespace dom {
 namespace quota {
 
 struct InitParams
 {
 };
 
@@ -120,13 +123,15 @@ parent:
 
   async PQuotaUsageRequest(UsageRequestParams params);
 
   async PQuotaRequest(RequestParams params);
 
   async StartIdleMaintenance();
 
   async StopIdleMaintenance();
+
+  async AbortOperationsForProcess(ContentParentId contentParentId);
 };
 
 } // namespace quota
 } // namespace dom
 } // namespace mozilla
--- a/dom/quota/QuotaManagerService.cpp
+++ b/dom/quota/QuotaManagerService.cpp
@@ -112,28 +112,16 @@ nsresult GetClearResetOriginParams(nsIPr
     aParams.clientTypeIsExplicit() = true;
   }
 
   aParams.matchAll() = aMatchAll;
 
   return NS_OK;
 }
 
-class AbortOperationsRunnable final : public Runnable {
-  ContentParentId mContentParentId;
-
- public:
-  explicit AbortOperationsRunnable(ContentParentId aContentParentId)
-      : Runnable("dom::quota::AbortOperationsRunnable"),
-        mContentParentId(aContentParentId) {}
-
- private:
-  NS_DECL_NSIRUNNABLE
-};
-
 }  // namespace
 
 class QuotaManagerService::PendingRequestInfo {
  protected:
   RefPtr<RequestBase> mRequest;
 
  public:
   explicit PendingRequestInfo(RequestBase* aRequest) : mRequest(aRequest) {}
@@ -235,45 +223,30 @@ already_AddRefed<QuotaManagerService> Qu
 }
 
 void QuotaManagerService::ClearBackgroundActor() {
   MOZ_ASSERT(NS_IsMainThread());
 
   mBackgroundActor = nullptr;
 }
 
-void QuotaManagerService::NoteLiveManager(QuotaManager* aManager) {
-  MOZ_ASSERT(XRE_IsParentProcess());
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aManager);
-
-  mBackgroundThread = aManager->OwningThread();
-}
-
-void QuotaManagerService::NoteShuttingDownManager() {
-  MOZ_ASSERT(XRE_IsParentProcess());
-  MOZ_ASSERT(NS_IsMainThread());
-
-  mBackgroundThread = nullptr;
-}
-
 void QuotaManagerService::AbortOperationsForProcess(
     ContentParentId aContentParentId) {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (!mBackgroundThread) {
+  nsresult rv = EnsureBackgroundActor();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  RefPtr<AbortOperationsRunnable> runnable =
-      new AbortOperationsRunnable(aContentParentId);
-
-  MOZ_ALWAYS_SUCCEEDS(
-      mBackgroundThread->Dispatch(runnable, NS_DISPATCH_NORMAL));
+  if (NS_WARN_IF(
+          !mBackgroundActor->SendAbortOperationsForProcess(aContentParentId))) {
+    return;
+  }
 }
 
 nsresult QuotaManagerService::Init() {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (XRE_IsParentProcess()) {
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
@@ -301,18 +274,19 @@ void QuotaManagerService::Destroy() {
     MOZ_ASSERT(false, "Shutdown more than once?!");
   }
 
   Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref);
 
   delete this;
 }
 
-nsresult QuotaManagerService::InitiateRequest(
-    nsAutoPtr<PendingRequestInfo>& aInfo) {
+nsresult QuotaManagerService::EnsureBackgroundActor() {
+  MOZ_ASSERT(NS_IsMainThread());
+
   // Nothing can be done here if we have previously failed to create a
   // background actor.
   if (mBackgroundActorFailed) {
     return NS_ERROR_FAILURE;
   }
 
   if (!mBackgroundActor) {
     PBackgroundChild* backgroundActor =
@@ -330,18 +304,27 @@ nsresult QuotaManagerService::InitiateRe
     }
   }
 
   if (!mBackgroundActor) {
     mBackgroundActorFailed = true;
     return NS_ERROR_FAILURE;
   }
 
-  // If we already have a background actor then we can start this request now.
-  nsresult rv = aInfo->InitiateRequest(mBackgroundActor);
+  return NS_OK;
+}
+
+nsresult QuotaManagerService::InitiateRequest(
+    nsAutoPtr<PendingRequestInfo>& aInfo) {
+  nsresult rv = EnsureBackgroundActor();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = aInfo->InitiateRequest(mBackgroundActor);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 void QuotaManagerService::PerformIdleMaintenance() {
@@ -823,34 +806,16 @@ QuotaManagerService::Observe(nsISupports
   return NS_OK;
 }
 
 void QuotaManagerService::Notify(const hal::BatteryInformation& aBatteryInfo) {
   // This notification is received when battery data changes. We don't need to
   // deal with this notification.
 }
 
-NS_IMETHODIMP
-AbortOperationsRunnable::Run() {
-  AssertIsOnBackgroundThread();
-
-  if (QuotaManager::IsShuttingDown()) {
-    return NS_OK;
-  }
-
-  QuotaManager* quotaManager = QuotaManager::Get();
-  if (!quotaManager) {
-    return NS_OK;
-  }
-
-  quotaManager->AbortOperationsForProcess(mContentParentId);
-
-  return NS_OK;
-}
-
 nsresult QuotaManagerService::UsageRequestInfo::InitiateRequest(
     QuotaChild* aActor) {
   MOZ_ASSERT(aActor);
 
   auto request = static_cast<UsageRequest*>(mRequest.get());
 
   auto actor = new QuotaUsageRequestChild(request);
 
--- a/dom/quota/QuotaManagerService.h
+++ b/dom/quota/QuotaManagerService.h
@@ -39,18 +39,16 @@ class QuotaManagerService final : public
   typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
 
   class BackgroundCreateCallback;
   class PendingRequestInfo;
   class UsageRequestInfo;
   class RequestInfo;
   class IdleMaintenanceInfo;
 
-  nsCOMPtr<nsIEventTarget> mBackgroundThread;
-
   QuotaChild* mBackgroundActor;
 
   bool mBackgroundActorFailed;
   bool mIdleObserverRegistered;
 
  public:
   // Returns a non-owning reference.
   static QuotaManagerService* GetOrCreate();
@@ -58,37 +56,31 @@ class QuotaManagerService final : public
   // Returns a non-owning reference.
   static QuotaManagerService* Get();
 
   // No one should call this but the factory.
   static already_AddRefed<QuotaManagerService> FactoryCreate();
 
   void ClearBackgroundActor();
 
-  void NoteLiveManager(QuotaManager* aManager);
-
-  void NoteShuttingDownManager();
-
   // Called when a process is being shot down. Aborts any running operations
   // for the given process.
   void AbortOperationsForProcess(ContentParentId aContentParentId);
 
  private:
   QuotaManagerService();
   ~QuotaManagerService();
 
   nsresult Init();
 
   void Destroy();
 
-  nsresult InitiateRequest(nsAutoPtr<PendingRequestInfo>& aInfo);
+  nsresult EnsureBackgroundActor();
 
-  nsresult BackgroundActorCreated(PBackgroundChild* aBackgroundActor);
-
-  void BackgroundActorFailed();
+  nsresult InitiateRequest(nsAutoPtr<PendingRequestInfo>& aInfo);
 
   void PerformIdleMaintenance();
 
   void RemoveIdleObserver();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIQUOTAMANAGERSERVICE
   NS_DECL_NSIOBSERVER