Bug 1035075 - Dispatch a runnable to wait for the PAC thread to shutdown. r=mcmanus
--- 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();