Bug 721603 - We should spin the loop after calling asyncClose in Database.cpp. r=mak.
authorRafael Ávila de Espíndola <respindola@mozilla.com>
Thu, 16 Feb 2012 07:03:53 -0500
changeset 86980 888416bbd8f30d61fb88521dc604d6701cea83d3
parent 86979 c1b718602a5ad36a41cbcfeb3383d2e3586926b9
child 86981 769f2cdb6ba63690345afd2e42c8cfa721587edd
push idunknown
push userunknown
push dateunknown
reviewersmak
bugs721603
milestone13.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 721603 - We should spin the loop after calling asyncClose in Database.cpp. r=mak.
toolkit/components/places/Database.cpp
toolkit/components/places/Helpers.cpp
toolkit/components/places/Helpers.h
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -246,16 +246,59 @@ SetJournalMode(nsCOMPtr<mozIStorageConne
     }
     // This is an unknown journal.
     MOZ_ASSERT(true);
   }
 
   return JOURNAL_DELETE;
 }
 
+class BlockingConnectionCloseCallback : public mozIStorageCompletionCallback {
+  bool mDone;
+
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
+  BlockingConnectionCloseCallback();
+  void Spin();
+};
+
+NS_IMETHODIMP
+BlockingConnectionCloseCallback::Complete()
+{
+  mDone = true;
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  MOZ_ASSERT(os);
+  if (!os)
+    return NS_OK;
+  DebugOnly<nsresult> rv = os->NotifyObservers(nsnull,
+                                               TOPIC_PLACES_CONNECTION_CLOSED,
+                                               nsnull);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  return NS_OK;
+}
+
+BlockingConnectionCloseCallback::BlockingConnectionCloseCallback()
+  : mDone(false)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+void BlockingConnectionCloseCallback::Spin() {
+  nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
+  while (!mDone) {
+    NS_ProcessNextEvent(thread);
+  }
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(
+  BlockingConnectionCloseCallback
+, mozIStorageCompletionCallback
+)
+
 nsresult
 CreateRoot(nsCOMPtr<mozIStorageConnection>& aDBConn,
            const nsCString& aRootName,
            const nsXPIDLString& titleString)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // The position of the new item in its folder.
@@ -1667,19 +1710,20 @@ Database::Shutdown()
   mMainThreadAsyncStatements.FinalizeStatements();
 
   nsRefPtr< FinalizeStatementCacheProxy<mozIStorageStatement> > event =
     new FinalizeStatementCacheProxy<mozIStorageStatement>(
           mAsyncThreadStatements, NS_ISUPPORTS_CAST(nsIObserver*, this)
         );
   DispatchToAsyncThread(event);
 
-  nsRefPtr<PlacesEvent> closeListener =
-    new PlacesEvent(TOPIC_PLACES_CONNECTION_CLOSED);
+  nsRefPtr<BlockingConnectionCloseCallback> closeListener =
+    new BlockingConnectionCloseCallback();
   (void)mMainConn->AsyncClose(closeListener);
+  closeListener->Spin();
 
   // Don't set this earlier, otherwise some internal helper used on shutdown
   // may bail out.
   mShuttingDown = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsIObserver
--- a/toolkit/components/places/Helpers.cpp
+++ b/toolkit/components/places/Helpers.cpp
@@ -395,36 +395,28 @@ PlacesEvent::PlacesEvent(const char* aTo
 
 NS_IMETHODIMP
 PlacesEvent::Run()
 {
   Notify();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-PlacesEvent::Complete()
-{
-  Notify();
-  return NS_OK;
-}
-
 void
 PlacesEvent::Notify()
 {
   NS_ASSERTION(NS_IsMainThread(), "Must only be used on the main thread!");
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     (void)obs->NotifyObservers(nsnull, mTopic, nsnull);
   }
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(
+NS_IMPL_THREADSAFE_ISUPPORTS1(
   PlacesEvent
-, mozIStorageCompletionCallback
 , nsIRunnable
 )
 
 ////////////////////////////////////////////////////////////////////////////////
 //// AsyncStatementCallbackNotifier
 
 NS_IMETHODIMP
 AsyncStatementCallbackNotifier::HandleCompletion(PRUint16 aReason)
--- a/toolkit/components/places/Helpers.h
+++ b/toolkit/components/places/Helpers.h
@@ -242,22 +242,20 @@ void ForceWALCheckpoint();
  */
 bool GetHiddenState(bool aIsRedirect,
                     PRUint32 aTransitionType);
 
 /**
  * Notifies a specified topic via the observer service.
  */
 class PlacesEvent : public nsRunnable
-                  , public mozIStorageCompletionCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
-  NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
 
   PlacesEvent(const char* aTopic);
 protected:
   void Notify();
 
   const char* const mTopic;
 };