Bug 744294 - nsPlacesAutoComplete doesn't wait for asyncClose to finish. r=asuth.
authorRafael Ávila de Espíndola <respindola@mozilla.com>
Tue, 08 May 2012 14:58:56 -0400
changeset 95791 9277703e34bddecba518de7d3a59a273cdca4d9c
parent 95790 e40ee1b66d6d74987819d1459be09277c173adf0
child 95792 54fb7607331873d1ed1b83b03007c71f8eed74bf
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs744294
milestone15.0a1
Bug 744294 - nsPlacesAutoComplete doesn't wait for asyncClose to finish. r=asuth.
storage/src/mozStorageConnection.cpp
storage/src/mozStorageConnection.h
storage/src/mozStorageService.cpp
--- 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,