Bug 1035075 - Dispatch a runnable to wait for the PAC thread to shutdown. r=mcmanus
authorDragana Damjanovic <dd.mozilla@gmail.com>
Thu, 14 Aug 2014 01:59:00 -0400
changeset 214771 8b5435b03ae8f3b64d4500e414d059c3ed4f6ff8
parent 214770 50076ac32c9e8147e9de8b3e48cb768fac0f7e04
child 214772 261d832d497bcc416a6dbdbfa6964e96f2fddf0d
push idunknown
push userunknown
push dateunknown
reviewersmcmanus
bugs1035075
milestone34.0a1
Bug 1035075 - Dispatch a runnable to wait for the PAC thread to shutdown. r=mcmanus
netwerk/base/src/nsPACMan.cpp
netwerk/base/src/nsPACMan.h
--- a/netwerk/base/src/nsPACMan.cpp
+++ b/netwerk/base/src/nsPACMan.cpp
@@ -108,16 +108,40 @@ public:
     mThread->Shutdown();
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIThread> mThread;
 };
 
+// Dispatch this to wait until the PAC thread shuts down.
+
+class WaitForThreadShutdown MOZ_FINAL : public nsRunnable
+{
+public:
+  explicit WaitForThreadShutdown(nsPACMan *aPACMan)
+    : mPACMan(aPACMan)
+  {
+  }
+
+  NS_IMETHODIMP Run()
+  {
+    NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
+    if (mPACMan->mPACThread) {
+      mPACMan->mPACThread->Shutdown();
+      mPACMan->mPACThread = nullptr;
+    }
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<nsPACMan> mPACMan;
+};
+
 //-----------------------------------------------------------------------------
 
 // PACLoadComplete allows the PAC thread to tell the main thread that
 // the javascript PAC file has been installed (perhaps unsuccessfully)
 // and that there is no reason to queue executions anymore
 
 class PACLoadComplete MOZ_FINAL : public nsRunnable
 {
@@ -287,19 +311,25 @@ nsPACMan::~nsPACMan()
   NS_ASSERTION(mLoader == nullptr, "pac man not shutdown properly");
   NS_ASSERTION(mPendingQ.isEmpty(), "pac man not shutdown properly");
 }
 
 void
 nsPACMan::Shutdown()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be shutdown on main thread");
-  CancelExistingLoad();
+  if (mShutdown) {
+    return;
+  }
   mShutdown = true;
+  CancelExistingLoad();
   PostCancelPendingQ(NS_ERROR_ABORT);
+
+  nsRefPtr<WaitForThreadShutdown> runnable = new WaitForThreadShutdown(this);
+  NS_DispatchToMainThread(runnable);
 }
 
 nsresult
 nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
                               bool mainThreadResponse)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
   if (mShutdown)
@@ -497,21 +527,22 @@ nsPACMan::CancelPendingQ(nsresult status
 }
 
 void
 nsPACMan::ProcessPendingQ()
 {
   NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
   while (ProcessPending());
 
-  // do GC while the thread has nothing pending
-  mPAC.GC();
-
-  if (mShutdown)
+  if (mShutdown) {
     mPAC.Shutdown();
+  } else {
+    // do GC while the thread has nothing pending
+    mPAC.GC();
+  }
 }
 
 // returns true if progress was made by shortening the queue
 bool
 nsPACMan::ProcessPending()
 {
   if (mPendingQ.isEmpty())
     return false;
--- a/netwerk/base/src/nsPACMan.h
+++ b/netwerk/base/src/nsPACMan.h
@@ -19,16 +19,17 @@
 #include "mozilla/LinkedList.h"
 #include "nsAutoPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "prlog.h"
 
 class nsPACMan;
 class nsISystemProxySettings;
 class nsIThread;
+class WaitForThreadShutdown;
 
 /**
  * This class defines a callback interface used by AsyncGetProxyForURI.
  */
 class NS_NO_VTABLE nsPACManCallback : public nsISupports
 {
 public:
   /**
@@ -159,16 +160,17 @@ public:
 private:
   NS_DECL_NSISTREAMLOADEROBSERVER
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSICHANNELEVENTSINK
 
   friend class PendingPACQuery;
   friend class PACLoadComplete;
   friend class ExecutePACThreadAction;
+  friend class WaitForThreadShutdown;
 
   ~nsPACMan();
 
   /**
    * Cancel any existing load if any.
    */
   void CancelExistingLoad();