Bug 1175387 - close file descriptor after detached from STS. r=mcmanus
authorLiang-Heng Chen <xeonchen@mozilla.com>
Tue, 04 Aug 2015 20:01:00 +0200
changeset 288003 1f6f47627dbd8ad7533f6ad86b5b305015af740a
parent 288002 c454836ffd1ee65b244c34e5d09e99ffd11fa966
child 288004 fec4e3434c44156033c2523fcd46f0fd5ff5e759
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus
bugs1175387
milestone42.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 1175387 - close file descriptor after detached from STS. r=mcmanus
netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
--- a/netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
+++ b/netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
@@ -60,52 +60,61 @@ public:
     }
 
     DNSServiceProcessResult(mService);
   }
 
   virtual void OnSocketDetached(PRFileDesc *fd) override
   {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+    MOZ_ASSERT(mThread);
     MOZ_ASSERT(fd == mFD);
 
     if (!mFD) {
       return;
     }
 
+    // Bug 1175387: do not double close the handle here.
+    PR_ChangeFileDescNativeHandle(mFD, -1);
     PR_Close(mFD);
     mFD = nullptr;
+
+    nsCOMPtr<nsIRunnable> ev =
+      NS_NewRunnableMethod(this, &ServiceWatcher::Deallocate);
+    mThread->Dispatch(ev, NS_DISPATCH_NORMAL);
   }
 
   virtual void IsLocal(bool *aIsLocal) override { *aIsLocal = true; }
 
   virtual void KeepWhenOffline(bool *aKeepWhenOffline) override
   {
     *aKeepWhenOffline = true;
   }
 
   virtual uint64_t ByteCountSent() override { return 0; }
   virtual uint64_t ByteCountReceived() override { return 0; }
 
   explicit ServiceWatcher(DNSServiceRef aService)
-    : mSts(nullptr)
+    : mThread(nullptr)
+    , mSts(nullptr)
     , mService(aService)
     , mFD(nullptr)
     , mAttached(false)
   {
     if (!gSocketTransportService)
     {
       nsCOMPtr<nsISocketTransportService> sts =
         do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
     }
   }
 
   nsresult Init()
   {
     MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
+    mThread = NS_GetCurrentThread();
 
     if (!mService) {
       return NS_OK;
     }
 
     if (!gSocketTransportService) {
       return NS_ERROR_FAILURE;
     }
@@ -119,31 +128,35 @@ public:
     mFD = PR_ImportFile(osfd);
     return PostEvent(&ServiceWatcher::OnMsgAttach);
   }
 
   void Close()
   {
     MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
 
-    if (mService) {
-      DNSServiceRefDeallocate(mService);
-      mService = nullptr;
-    }
-
     if (!gSocketTransportService) {
+      Deallocate();
       return;
     }
 
     PostEvent(&ServiceWatcher::OnMsgClose);
   }
 
 private:
   ~ServiceWatcher() = default;
 
+  void Deallocate()
+  {
+    if (mService) {
+      DNSServiceRefDeallocate(mService);
+      mService = nullptr;
+    }
+  }
+
   nsresult PostEvent(void(ServiceWatcher::*func)(void))
   {
     nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, func);
     return gSocketTransportService->Dispatch(ev, NS_DISPATCH_NORMAL);
   }
 
   void OnMsgClose()
   {
@@ -227,16 +240,17 @@ private:
     //
     // now, configure our poll flags for listening...
     //
     mPollFlags = (PR_POLL_READ | PR_POLL_EXCEPT);
 
     return NS_OK;
   }
 
+  nsCOMPtr<nsIThread> mThread;
   nsRefPtr<nsSocketTransportService> mSts;
   DNSServiceRef mService;
   PRFileDesc* mFD;
   bool mAttached;
 };
 
 NS_IMPL_ISUPPORTS(MDNSResponderOperator::ServiceWatcher, nsISupports)