Bug 1297481 - add shutdown state to protocolproxyservice draft
authorPatrick McManus <mcmanus@ducksong.com>
Wed, 19 Apr 2017 08:42:09 -0400
changeset 565054 32fb0700e92b0ccc142c298377c7d9ac921da0d0
parent 565030 c0ea5ed7f91a6be996a4a3c5ab25e2cdf6b4377e
child 624906 e55fedda78918fb5fc57f1a96b5056c5e1c96d11
push id54776
push userbmo:mcmanus@ducksong.com
push dateWed, 19 Apr 2017 12:52:44 +0000
bugs1297481
milestone55.0a1
Bug 1297481 - add shutdown state to protocolproxyservice the protocol proxy service asserts that is in a clean state at dtor - normally this happens through observe("xpcom-shutdown") but its actually possible of other events in the xpcom run queue to 'unitialize' things before the dtor.. add a state in which fail codes are returned instead. MozReview-Commit-ID: XaNQEZUsRP
netwerk/base/nsProtocolProxyService.cpp
netwerk/base/nsProtocolProxyService.h
--- a/netwerk/base/nsProtocolProxyService.cpp
+++ b/netwerk/base/nsProtocolProxyService.cpp
@@ -423,16 +423,17 @@ nsProtocolProxyService::nsProtocolProxyS
     , mHTTPSProxyPort(-1)
     , mSOCKSProxyPort(-1)
     , mSOCKSProxyVersion(4)
     , mSOCKSProxyRemoteDNS(false)
     , mProxyOverTLS(true)
     , mPACMan(nullptr)
     , mSessionStart(PR_Now())
     , mFailedProxyTimeout(30 * 60) // 30 minute default
+    , mIsShutdown(false)
 {
 }
 
 nsProtocolProxyService::~nsProtocolProxyService()
 {
     // These should have been cleaned up in our Observe method.
     NS_ASSERTION(mHostFiltersArray.Length() == 0 && mFilters == nullptr &&
                  mPACMan == nullptr, "what happened to xpcom-shutdown?");
@@ -513,16 +514,17 @@ nsProtocolProxyService::ReloadNetworkPAC
 
 
 NS_IMETHODIMP
 nsProtocolProxyService::Observe(nsISupports     *aSubject,
                                 const char      *aTopic,
                                 const char16_t *aData)
 {
     if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
+        mIsShutdown = true;
         // cleanup
         if (mHostFiltersArray.Length() > 0) {
             mHostFiltersArray.Clear();
         }
         if (mFilters) {
             delete mFilters;
             mFilters = nullptr;
         }
@@ -1012,16 +1014,20 @@ nsProtocolProxyService::IsProxyDisabled(
     }
 
     return true;
 }
 
 nsresult
 nsProtocolProxyService::SetupPACThread()
 {
+    if (mIsShutdown) {
+        return NS_ERROR_FAILURE;
+    }
+
     if (mPACMan)
         return NS_OK;
 
     mPACMan = new nsPACMan();
 
     bool mainThreadOnly;
     nsresult rv;
     if (mSystemProxySettings &&
@@ -1048,17 +1054,18 @@ nsProtocolProxyService::ResetPACThread()
     mPACMan = nullptr;
     return SetupPACThread();
 }
 
 nsresult
 nsProtocolProxyService::ConfigureFromPAC(const nsCString &spec,
                                          bool forceReload)
 {
-    SetupPACThread();
+    nsresult rv = SetupPACThread();
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if (mPACMan->IsPACURI(spec) && !forceReload)
         return NS_OK;
 
     mFailedProxies.Clear();
 
     return mPACMan->LoadPACFromURI(spec);
 }
@@ -1369,16 +1376,20 @@ nsProtocolProxyService::GetFailoverForPr
 
     NS_ADDREF(*aResult = pi->mNext);
     return NS_OK;
 }
 
 nsresult
 nsProtocolProxyService::InsertFilterLink(FilterLink *link, uint32_t position)
 {
+    if (mIsShutdown) {
+        return NS_ERROR_FAILURE;
+    }
+
     if (!mFilters) {
         mFilters = link;
         return NS_OK;
     }
 
     // insert into mFilters in sorted order
     FilterLink *last = nullptr;
     for (FilterLink *iter = mFilters; iter; iter = iter->next) {
@@ -1405,30 +1416,38 @@ nsProtocolProxyService::RegisterFilter(n
                                        uint32_t position)
 {
     UnregisterFilter(filter); // remove this filter if we already have it
 
     FilterLink *link = new FilterLink(position, filter);
     if (!link) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
-    return InsertFilterLink(link, position);
+    nsresult rv = InsertFilterLink(link, position);
+    if (NS_FAILED(rv)) {
+        delete link;
+    }
+    return rv;
 }
 
 NS_IMETHODIMP
 nsProtocolProxyService::RegisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter,
                                               uint32_t position)
 {
     UnregisterChannelFilter(channelFilter);  // remove this filter if we already have it
 
     FilterLink *link = new FilterLink(position, channelFilter);
     if (!link) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
-    return InsertFilterLink(link, position);
+    nsresult rv = InsertFilterLink(link, position);
+    if (NS_FAILED(rv)) {
+        delete link;
+    }
+    return rv;
 }
 
 nsresult
 nsProtocolProxyService::RemoveFilterLink(nsISupports* givenObject)
 {
     FilterLink *last = nullptr;
     for (FilterLink *iter = mFilters; iter; iter = iter->next) {
         nsCOMPtr<nsISupports> object = do_QueryInterface(iter->filter);
@@ -1468,16 +1487,20 @@ nsProtocolProxyService::GetProxyConfigTy
 {
   *aProxyConfigType = mProxyConfig;
   return NS_OK;
 }
 
 void
 nsProtocolProxyService::LoadHostFilters(const nsACString& aFilters)
 {
+    if (mIsShutdown) {
+        return;
+    }
+
     // check to see the owners flag? /!?/ TODO
     if (mHostFiltersArray.Length() > 0) {
         mHostFiltersArray.Clear();
     }
 
     if (aFilters.IsEmpty()) {
         return;
     }
--- a/netwerk/base/nsProtocolProxyService.h
+++ b/netwerk/base/nsProtocolProxyService.h
@@ -395,17 +395,17 @@ protected:
     nsFailedProxyTable           mFailedProxies;
     int32_t                      mFailedProxyTimeout;
 
 private:
     nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
                                   nsIProtocolProxyCallback *callback,
                                   nsICancelable **result,
                                   bool isSyncOK);
-
+    bool                          mIsShutdown;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService, NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)
 
 } // namespace net
 } // namespace mozilla
 
 #endif // !nsProtocolProxyService_h__