Bug 1376676 - Avoid a race condition where the History.cpp cloned connection may not be closed. r=asuth
authorMarco Bonardo <mbonardo@mozilla.com>
Mon, 24 Jul 2017 23:08:44 +0200
changeset 370738 44260a3e2218dc95c04eda70e9fb3c2e60a034b9
parent 370737 1c8ae3d9f7c2973a8a1c132a55b46cbb96f2db97
child 370739 5227744e2508312d6c92f122efc9d171c58c07bb
push id47166
push usermak77@bonardo.net
push dateTue, 25 Jul 2017 09:55:18 +0000
treeherderautoland@44260a3e2218 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1376676
milestone56.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 1376676 - Avoid a race condition where the History.cpp cloned connection may not be closed. r=asuth MozReview-Commit-ID: YXmasMLBg4
toolkit/components/places/History.cpp
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -1997,25 +1997,33 @@ History::NotifyVisited(nsIURI* aURI)
   return NS_OK;
 }
 
 class ConcurrentStatementsHolder final : public mozIStorageCompletionCallback {
 public:
   NS_DECL_ISUPPORTS
 
   explicit ConcurrentStatementsHolder(mozIStorageConnection* aDBConn)
+  : mShutdownWasInvoked(false)
   {
     DebugOnly<nsresult> rv = aDBConn->AsyncClone(true, this);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   NS_IMETHOD Complete(nsresult aStatus, nsISupports* aConnection) override {
-    if (NS_FAILED(aStatus))
+    if (NS_FAILED(aStatus)) {
       return NS_OK;
+    }
     mReadOnlyDBConn = do_QueryInterface(aConnection);
+    // It's possible Shutdown was invoked before we were handed back the
+    // cloned connection handle.
+    if (mShutdownWasInvoked) {
+      Shutdown();
+      return NS_OK;
+    }
 
     // Now we can create our cached statements.
 
     if (!mIsVisitedStatement) {
       (void)mReadOnlyDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
         "SELECT 1 FROM moz_places h "
         "WHERE url_hash = hash(?1) AND url = ?1 AND last_visit_date NOTNULL "
       ),  getter_AddRefs(mIsVisitedStatement));
@@ -2040,36 +2048,39 @@ public:
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     } else {
       DebugOnly<bool> added = mIsVisitedCallbacks.AppendObject(aCallback);
       MOZ_ASSERT(added);
     }
   }
 
   void Shutdown() {
+    mShutdownWasInvoked = true;
     if (mReadOnlyDBConn) {
       mIsVisitedCallbacks.Clear();
       DebugOnly<nsresult> rv;
       if (mIsVisitedStatement) {
         rv = mIsVisitedStatement->Finalize();
         MOZ_ASSERT(NS_SUCCEEDED(rv));
       }
       rv = mReadOnlyDBConn->AsyncClose(nullptr);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
+      mReadOnlyDBConn = nullptr;
     }
   }
 
 private:
   ~ConcurrentStatementsHolder()
   {
   }
 
   nsCOMPtr<mozIStorageAsyncConnection> mReadOnlyDBConn;
   nsCOMPtr<mozIStorageAsyncStatement> mIsVisitedStatement;
   nsCOMArray<mozIStorageCompletionCallback> mIsVisitedCallbacks;
+  bool mShutdownWasInvoked;
 };
 
 NS_IMPL_ISUPPORTS(
   ConcurrentStatementsHolder
 , mozIStorageCompletionCallback
 )
 
 nsresult