Bug 883495 - Avoid releasing a scriptable DNS listener off the main thread. r=mcmanus
authorJosh Matthews <josh@joshmatthews.net>
Thu, 20 Jun 2013 09:18:16 +0200
changeset 135808 1c1ae670a995e8d5621a264fdc7fffdff2eb23cd
parent 135807 89cceb4bb3dbbf515eec6dcec68ed5efab271c41
child 135809 457bf850bf0448822da272d31ea763873b950c53
push idunknown
push userunknown
push dateunknown
reviewersmcmanus
bugs883495
milestone24.0a1
Bug 883495 - Avoid releasing a scriptable DNS listener off the main thread. r=mcmanus
netwerk/dns/nsDNSService2.cpp
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -250,30 +250,34 @@ public:
 
     nsDNSAsyncRequest(nsHostResolver   *res,
                       const nsACString &host,
                       nsIDNSListener   *listener,
                       uint16_t          flags,
                       uint16_t          af)
         : mResolver(res)
         , mHost(host)
-        , mListener(listener)
+        // Sometimes aListener is a main-thread only object like XPCWrappedJS, and
+        // sometimes it's a threadsafe object like nsSocketTransport. Use a main-
+        // thread pointer holder, but disable strict enforcement of thread invariants.
+        // The AddRef implementation of XPCWrappedJS will assert if we go wrong here.
+        , mListener(new nsMainThreadPtrHolder<nsIDNSListener>(listener, false))
         , mFlags(flags)
         , mAF(af) {}
     ~nsDNSAsyncRequest() {}
 
     void OnLookupComplete(nsHostResolver *, nsHostRecord *, nsresult);
     // Returns TRUE if the DNS listener arg is the same as the member listener
     // Used in Cancellations to remove DNS requests associated with a
     // particular hostname and nsIDNSListener
     bool EqualsAsyncListener(nsIDNSListener *aListener);
 
     nsRefPtr<nsHostResolver> mResolver;
     nsCString                mHost; // hostname we're resolving
-    nsCOMPtr<nsIDNSListener> mListener;
+    nsMainThreadPtrHandle<nsIDNSListener> mListener;
     uint16_t                 mFlags;
     uint16_t                 mAF;
 };
 
 void
 nsDNSAsyncRequest::OnLookupComplete(nsHostResolver *resolver,
                                     nsHostRecord   *hostRecord,
                                     nsresult        status)
@@ -287,17 +291,17 @@ nsDNSAsyncRequest::OnLookupComplete(nsHo
         rec = new nsDNSRecord(hostRecord);
         if (!rec)
             status = NS_ERROR_OUT_OF_MEMORY;
     }
 
     MOZ_EVENT_TRACER_DONE(this, "net::dns::lookup");
 
     mListener->OnLookupComplete(this, rec, status);
-    mListener = nullptr;
+    mListener = nsMainThreadPtrHandle<nsIDNSListener>();
 
     // release the reference to ourselves that was added before we were
     // handed off to the host resolver.
     NS_RELEASE_THIS();
 }
 
 bool
 nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener *aListener)