Bug 729536 - Deadlock by xul!nsHttpConnectionMgr::Shutdown. r=cbiesinger, a=lsblakk
authorHonza Bambas <honzab.moz@firemni.cz>
Mon, 22 Oct 2012 19:59:07 +0200
changeset 109741 4337f296f25e2c6bf308207f3bd88abd944da666
parent 109740 5c16cf77238e3ebaa03c53220434b9b931c101e2
child 109742 2584cac54ea7f1772d0023bc3b879ae87d8dff97
push id1641
push userryanvm@gmail.com
push dateTue, 30 Oct 2012 16:11:39 +0000
treeherdermozilla-beta@4337f296f25e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscbiesinger, lsblakk
bugs729536
milestone17.0
Bug 729536 - Deadlock by xul!nsHttpConnectionMgr::Shutdown. r=cbiesinger, a=lsblakk
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpConnectionMgr.h
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -129,37 +129,43 @@ nsHttpConnectionMgr::Init(uint16_t maxCo
     return EnsureSocketThreadTargetIfOnline();
 }
 
 nsresult
 nsHttpConnectionMgr::Shutdown()
 {
     LOG(("nsHttpConnectionMgr::Shutdown\n"));
 
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    // do nothing if already shutdown
-    if (!mSocketThreadTarget)
-        return NS_OK;
-
-    nsresult rv = PostEvent(&nsHttpConnectionMgr::OnMsgShutdown);
-
-    // release our reference to the STS to prevent further events
-    // from being posted.  this is how we indicate that we are
-    // shutting down.
-    mIsShuttingDown = true;
-    mSocketThreadTarget = 0;
-
-    if (NS_FAILED(rv)) {
-        NS_WARNING("unable to post SHUTDOWN message");
-        return rv;
+    bool shutdown = false;
+    {
+        ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+        // do nothing if already shutdown
+        if (!mSocketThreadTarget)
+            return NS_OK;
+
+        nsresult rv = PostEvent(&nsHttpConnectionMgr::OnMsgShutdown,
+                                0, &shutdown);
+
+        // release our reference to the STS to prevent further events
+        // from being posted.  this is how we indicate that we are
+        // shutting down.
+        mIsShuttingDown = true;
+        mSocketThreadTarget = 0;
+
+        if (NS_FAILED(rv)) {
+            NS_WARNING("unable to post SHUTDOWN message");
+            return rv;
+        }
     }
 
     // wait for shutdown event to complete
-    mon.Wait();
+    while (!shutdown)
+        NS_ProcessNextEvent(NS_GetCurrentThread());
+
     return NS_OK;
 }
 
 nsresult
 nsHttpConnectionMgr::PostEvent(nsConnEventHandler handler, int32_t iparam, void *vparam)
 {
     // This object doesn't get reinitialized if the offline state changes, so our
     // socket thread target might be uninitialized if we were offline when this
@@ -1839,32 +1845,44 @@ nsHttpConnectionMgr::GetSpdyPreferredCon
     }
     
     return conn;
 }
 
 //-----------------------------------------------------------------------------
 
 void
-nsHttpConnectionMgr::OnMsgShutdown(int32_t, void *)
+nsHttpConnectionMgr::OnMsgShutdown(int32_t, void *param)
 {
     NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
     LOG(("nsHttpConnectionMgr::OnMsgShutdown\n"));
 
     mCT.Enumerate(ShutdownPassCB, this);
 
     if (mTimeoutTick) {
         mTimeoutTick->Cancel();
         mTimeoutTick = nullptr;
         mTimeoutTickArmed = false;
     }
     
     // signal shutdown complete
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    mon.Notify();
+    nsRefPtr<nsIRunnable> runnable = 
+        new nsConnEvent(this, &nsHttpConnectionMgr::OnMsgShutdownConfirm,
+                        0, param);
+    NS_DispatchToMainThread(runnable);
+}
+
+void
+nsHttpConnectionMgr::OnMsgShutdownConfirm(int32_t priority, void *param)
+{
+    NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
+    LOG(("nsHttpConnectionMgr::OnMsgShutdownConfirm\n"));
+
+    bool *shutdown = static_cast<bool*>(param);
+    *shutdown = true;
 }
 
 void
 nsHttpConnectionMgr::OnMsgNewTransaction(int32_t priority, void *param)
 {
     LOG(("nsHttpConnectionMgr::OnMsgNewTransaction [trans=%p]\n", param));
 
     nsHttpTransaction *trans = (nsHttpTransaction *) param;
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -556,16 +556,17 @@ private:
     };
 
     nsresult PostEvent(nsConnEventHandler  handler,
                        int32_t             iparam = 0,
                        void               *vparam = nullptr);
 
     // message handlers
     void OnMsgShutdown             (int32_t, void *);
+    void OnMsgShutdownConfirm      (int32_t, void *);
     void OnMsgNewTransaction       (int32_t, void *);
     void OnMsgReschedTransaction   (int32_t, void *);
     void OnMsgCancelTransaction    (int32_t, void *);
     void OnMsgProcessPendingQ      (int32_t, void *);
     void OnMsgPruneDeadConnections (int32_t, void *);
     void OnMsgSpeculativeConnect   (int32_t, void *);
     void OnMsgReclaimConnection    (int32_t, void *);
     void OnMsgCompleteUpgrade      (int32_t, void *);