Bug 744294 - nsPlacesAutoComplete doesn't wait for asyncClose to finish. r=asuth.
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -808,16 +808,25 @@ Connection::setClosedState()
MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
NS_ENSURE_FALSE(mAsyncExecutionThreadShuttingDown, NS_ERROR_UNEXPECTED);
mAsyncExecutionThreadShuttingDown = true;
}
return NS_OK;
}
+bool
+Connection::isAsyncClosing() {
+ MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
+ bool isReady;
+ (void)GetConnectionReady(&isReady);
+ return mAsyncExecutionThreadShuttingDown && !!mAsyncExecutionThread &&
+ isReady;
+}
+
nsresult
Connection::internalClose()
{
#ifdef DEBUG
// Sanity checks to make sure we are in the proper state before calling this.
NS_ASSERTION(mDBConn, "Database connection is already null!");
{ // Make sure we have marked our async thread as shutting down.
--- a/storage/src/mozStorageConnection.h
+++ b/storage/src/mozStorageConnection.h
@@ -170,16 +170,22 @@ public:
* when not on the main thread by waiting until we are notified.
*
* @param aStatement
* A pointer to a sqlite3_stmt object.
* @return the result from sqlite3_step.
*/
int stepStatement(sqlite3_stmt* aStatement);
+ /**
+ * True if this is an async connection, it is shutting down and it is not
+ * closed yet.
+ */
+ bool isAsyncClosing();
+
private:
~Connection();
/**
* Sets the database into a closed state so no further actions can be
* performed.
*
* @note mDBConn is set to NULL in this method.
--- a/storage/src/mozStorageService.cpp
+++ b/storage/src/mozStorageService.cpp
@@ -342,16 +342,18 @@ public:
// Register for xpcom-shutdown so we can cleanup after ourselves. The
// observer service can only be used on the main thread.
nsCOMPtr<nsIObserverService> os =
mozilla::services::GetObserverService();
NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
nsresult rv = os->AddObserver(mObserver, "xpcom-shutdown", false);
NS_ENSURE_SUCCESS(rv, rv);
+ rv = os->AddObserver(mObserver, "xpcom-shutdown-threads", false);
+ NS_ENSURE_SUCCESS(rv, rv);
// We cache XPConnect for our language helpers. XPConnect can only be
// used on the main thread.
(void)CallGetService(nsIXPConnect::GetCID(), mXPConnectPtr);
// We need to obtain the toolkit.storage.synchronous preferences on the main
// thread because the preference service can only be accessed there. This
// is cached in the service for all future Open[Unshared]Database calls.
@@ -849,16 +851,42 @@ Service::BackupDatabaseFile(nsIFile *aDB
////////////////////////////////////////////////////////////////////////////////
//// nsIObserver
NS_IMETHODIMP
Service::Observe(nsISupports *, const char *aTopic, const PRUnichar *)
{
if (strcmp(aTopic, "xpcom-shutdown") == 0)
shutdown();
+ if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) {
+ nsCOMPtr<nsIObserverService> os =
+ mozilla::services::GetObserverService();
+ os->RemoveObserver(this, "xpcom-shutdown-threads");
+ bool anyOpen = false;
+ do {
+ nsTArray<nsRefPtr<Connection> > connections;
+ getConnections(connections);
+ anyOpen = false;
+ for (PRUint32 i = 0; i < connections.Length(); i++) {
+ nsRefPtr<Connection> &conn = connections[i];
+
+ // While it would be nice to close all connections, we only
+ // check async ones for now.
+ if (conn->isAsyncClosing()) {
+ anyOpen = true;
+ break;
+ }
+ }
+ if (anyOpen) {
+ nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
+ NS_ProcessNextEvent(thread);
+ }
+ } while (anyOpen);
+ }
+
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// mozIStorageServiceQuotaManagement
NS_IMETHODIMP
Service::OpenDatabaseWithVFS(nsIFile *aDatabaseFile,