Bug 1621051 - Add a mutext to protect mRestrictedPortList,r=valentin
authorKershaw Chang <kershaw@mozilla.com>
Mon, 09 Mar 2020 19:03:27 +0000
changeset 517687 2be4c9a3f053fa67f0d821e926c49abe2a947654
parent 517686 cc4ec8298e520d16655ff7e8f6a86a32cc423206
child 517688 6364375772b69178d47b251a4035432d28813257
push id37199
push useropoprus@mozilla.com
push dateTue, 10 Mar 2020 03:43:44 +0000
treeherdermozilla-central@6f21f98dcfcd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin
bugs1621051
milestone76.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 1621051 - Add a mutext to protect mRestrictedPortList,r=valentin Differential Revision: https://phabricator.services.mozilla.com/D66086
netwerk/base/nsIOService.cpp
netwerk/base/nsIOService.h
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -195,16 +195,17 @@ nsIOService::nsIOService()
       mOfflineMirrorsConnectivity(true),
       mSettingOffline(false),
       mSetOfflineValue(false),
       mSocketProcessLaunchComplete(false),
       mShutdown(false),
       mHttpHandlerAlreadyShutingDown(false),
       mNetworkLinkServiceInitialized(false),
       mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY),
+      mMutex("nsIOService::mMutex"),
       mTotalRequests(0),
       mCacheWon(0),
       mNetWon(0),
       mLastOfflineStateChange(PR_IntervalNow()),
       mLastConnectivityChange(PR_IntervalNow()),
       mLastNetworkLinkChange(PR_IntervalNow()),
       mNetTearingDownStarted(0),
       mSocketProcess(nullptr) {}
@@ -1316,25 +1317,35 @@ nsIOService::AllowPort(int32_t inPort, c
     return NS_OK;
   }
 
   if (port == 0) {
     *_retval = false;
     return NS_OK;
   }
 
+  nsTArray<int32_t> restrictedPortList;
+  {
+    MutexAutoLock lock(mMutex);
+    restrictedPortList.Assign(mRestrictedPortList);
+  }
+
   // first check to see if the port is in our blacklist:
-  int32_t badPortListCnt = mRestrictedPortList.Length();
+  int32_t badPortListCnt = restrictedPortList.Length();
   for (int i = 0; i < badPortListCnt; i++) {
-    if (port == mRestrictedPortList[i]) {
+    if (port == restrictedPortList[i]) {
       *_retval = false;
 
       // check to see if the protocol wants to override
       if (!scheme) return NS_OK;
 
+      // We don't support get protocol handler off main thread.
+      if (!NS_IsMainThread()) {
+        return NS_OK;
+      }
       nsCOMPtr<nsIProtocolHandler> handler;
       nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
       if (NS_FAILED(rv)) return rv;
 
       // let the protocol handler decide
       return handler->AllowPort(port, scheme, _retval);
     }
   }
@@ -1402,51 +1413,58 @@ void nsIOService::PrefsChanged(const cha
         static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Stop();
       }
     }
   }
 }
 
 void nsIOService::ParsePortList(const char* pref, bool remove) {
   nsAutoCString portList;
-
+  nsTArray<int32_t> restrictedPortList;
+  {
+    MutexAutoLock lock(mMutex);
+    restrictedPortList.Assign(std::move(mRestrictedPortList));
+  }
   // Get a pref string and chop it up into a list of ports.
   Preferences::GetCString(pref, portList);
   if (!portList.IsVoid()) {
     nsTArray<nsCString> portListArray;
     ParseString(portList, ',', portListArray);
     uint32_t index;
     for (index = 0; index < portListArray.Length(); index++) {
       portListArray[index].StripWhitespace();
       int32_t portBegin, portEnd;
 
       if (PR_sscanf(portListArray[index].get(), "%d-%d", &portBegin,
                     &portEnd) == 2) {
         if ((portBegin < 65536) && (portEnd < 65536)) {
           int32_t curPort;
           if (remove) {
             for (curPort = portBegin; curPort <= portEnd; curPort++)
-              mRestrictedPortList.RemoveElement(curPort);
+              restrictedPortList.RemoveElement(curPort);
           } else {
             for (curPort = portBegin; curPort <= portEnd; curPort++)
-              mRestrictedPortList.AppendElement(curPort);
+              restrictedPortList.AppendElement(curPort);
           }
         }
       } else {
         nsresult aErrorCode;
         int32_t port = portListArray[index].ToInteger(&aErrorCode);
         if (NS_SUCCEEDED(aErrorCode) && port < 65536) {
           if (remove)
-            mRestrictedPortList.RemoveElement(port);
+            restrictedPortList.RemoveElement(port);
           else
-            mRestrictedPortList.AppendElement(port);
+            restrictedPortList.AppendElement(port);
         }
       }
     }
   }
+
+  MutexAutoLock lock(mMutex);
+  mRestrictedPortList.Assign(std::move(restrictedPortList));
 }
 
 class nsWakeupNotifier : public Runnable {
  public:
   explicit nsWakeupNotifier(nsIIOServiceInternal* ioService)
       : Runnable("net::nsWakeupNotifier"), mIOService(ioService) {}
 
   NS_IMETHOD Run() override { return mIOService->NotifyWakeup(); }
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -14,16 +14,17 @@
 #include "nsIWeakReferenceUtils.h"
 #include "nsINetUtil.h"
 #include "nsIChannelEventSink.h"
 #include "nsCategoryCache.h"
 #include "nsISpeculativeConnect.h"
 #include "nsDataHashtable.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Mutex.h"
 #include "prtime.h"
 #include "nsICaptivePortalService.h"
 
 #define NS_N(x) (sizeof(x) / sizeof(*x))
 
 // We don't want to expose this observer topic.
 // Intended internal use only for remoting offline/inline events.
 // See Bug 552829
@@ -214,16 +215,17 @@ class nsIOService final : public nsIIOSe
   bool mNetworkLinkServiceInitialized;
 
   // Cached protocol handlers, only accessed on the main thread
   nsWeakPtr mWeakHandler[NS_N(gScheme)];
 
   // cached categories
   nsCategoryCache<nsIChannelEventSink> mChannelEventSinks;
 
+  Mutex mMutex;
   nsTArray<int32_t> mRestrictedPortList;
 
   static bool sIsDataURIUniqueOpaqueOrigin;
   static bool sBlockToplevelDataUriNavigations;
 
   uint32_t mTotalRequests;
   uint32_t mCacheWon;
   uint32_t mNetWon;