Bug 1558112 - LSNG: Connection::FlushOp::DoDatastoreWork needs to automatically detach the shadow database on an error; r=asuth a=jcristau
authorJan Varga <jan.varga@gmail.com>
Mon, 10 Jun 2019 08:41:13 +0200
changeset 536831 09ffb8ef4a65d03211b31bbe0bf1ea526351a0b7
parent 536830 eb71282f69a503677fe8a8fecabe38212149fbe9
child 536832 640a6522039241236b6377aa9707485776783883
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth, jcristau
bugs1558112
milestone68.0
Bug 1558112 - LSNG: Connection::FlushOp::DoDatastoreWork needs to automatically detach the shadow database on an error; r=asuth a=jcristau Differential Revision: https://phabricator.services.mozilla.com/D34311
dom/localstorage/ActorsParent.cpp
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -4643,37 +4643,69 @@ Connection::FlushOp::FlushOp(Connection*
     : ConnectionDatastoreOperationBase(aConnection),
       mWriteOptimizer(std::move(aWriteOptimizer)),
       mShadowWrites(gShadowWrites) {}
 
 nsresult Connection::FlushOp::DoDatastoreWork() {
   AssertIsOnConnectionThread();
   MOZ_ASSERT(mConnection);
 
+  class MOZ_STACK_CLASS AutoDetach final {
+    nsCOMPtr<mozIStorageConnection> mConnection;
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+   public:
+    explicit AutoDetach(
+        mozIStorageConnection* aConnection MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+        : mConnection(aConnection) {
+      MOZ_ASSERT(aConnection);
+
+      MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+    ~AutoDetach() {
+      if (mConnection) {
+        nsresult rv = DetachShadowDatabase(mConnection);
+        Unused << NS_WARN_IF(NS_FAILED(rv));
+      }
+    }
+
+    void release() { mConnection = nullptr; }
+
+   private:
+    explicit AutoDetach(const AutoDetach&) = delete;
+    AutoDetach& operator=(const AutoDetach&) = delete;
+    AutoDetach& operator=(AutoDetach&&) = delete;
+  };
+
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
   nsCOMPtr<mozIStorageConnection> storageConnection =
       mConnection->StorageConnection();
   MOZ_ASSERT(storageConnection);
 
   nsresult rv;
 
   Maybe<MutexAutoLock> shadowDatabaseLock;
 
+  Maybe<AutoDetach> autoDetach;
+
   if (mShadowWrites) {
     MOZ_ASSERT(mConnection->mQuotaClient);
 
     shadowDatabaseLock.emplace(
         mConnection->mQuotaClient->ShadowDatabaseMutex());
 
     rv = AttachShadowDatabase(quotaManager->GetBasePath(), storageConnection);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
+
+    autoDetach.emplace(storageConnection);
   }
 
   CachedStatement stmt;
   rv = mConnection->GetCachedStatement(NS_LITERAL_CSTRING("BEGIN IMMEDIATE;"),
                                        &stmt);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -4713,21 +4745,25 @@ nsresult Connection::FlushOp::DoDatastor
   }
 
   rv = stmt->Execute();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (mShadowWrites) {
+    autoDetach->release();
+
     rv = DetachShadowDatabase(storageConnection);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
+    autoDetach.reset();
+
     shadowDatabaseLock.reset();
   }
 
   rv = usageJournalFile->Remove(false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }