Bug 1376676 - Avoid a race condition where the History.cpp cloned connection may not be closed. r=asuth
MozReview-Commit-ID: YXmasMLBg4
--- 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