Bug 1381005 - Add some diagnostic assertions to figure out why mEnt is null. This is only temporary. r=mcmanus
authorDragana Damjanovic dd.mozilla@gmail.com
Mon, 17 Jul 2017 23:59:29 +0200
changeset 369384 59c86ba2610141e0c9fa82defdae58f919a5c6bd
parent 369383 bdcd3e78b4c051dd383a26ea4172b0ccdb62feaf
child 369385 a201b7d3ed0235ebe59aee45b44d5376b230dcc2
push id32195
push userryanvm@gmail.com
push dateTue, 18 Jul 2017 16:15:01 +0000
treeherdermozilla-central@56c6c81993e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus
bugs1381005
milestone56.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 1381005 - Add some diagnostic assertions to figure out why mEnt is null. This is only temporary. r=mcmanus
netwerk/protocol/http/ConnectionDiagnostics.cpp
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/protocol/http/nsHttpConnection.h
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpConnectionMgr.h
--- a/netwerk/protocol/http/ConnectionDiagnostics.cpp
+++ b/netwerk/protocol/http/ConnectionDiagnostics.cpp
@@ -44,17 +44,17 @@ nsHttpConnectionMgr::OnMsgPrintDiagnosti
 
   mLogData.AppendPrintf("HTTP Connection Diagnostics\n---------------------\n");
   mLogData.AppendPrintf("IsSpdyEnabled() = %d\n", gHttpHandler->IsSpdyEnabled());
   mLogData.AppendPrintf("MaxSocketCount() = %d\n", gHttpHandler->MaxSocketCount());
   mLogData.AppendPrintf("mNumActiveConns = %d\n", mNumActiveConns);
   mLogData.AppendPrintf("mNumIdleConns = %d\n", mNumIdleConns);
 
   for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-    nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+    RefPtr<nsConnectionEntry> ent = iter.Data();
 
     mLogData.AppendPrintf(" ent host = %s hashkey = %s\n",
                           ent->mConnInfo->Origin(), ent->mConnInfo->HashKey().get());
     mLogData.AppendPrintf("   AtActiveConnectionLimit = %d\n",
                           AtActiveConnectionLimit(ent, NS_HTTP_ALLOW_KEEPALIVE));
     mLogData.AppendPrintf("   RestrictConnections = %d\n",
                           RestrictConnections(ent));
     mLogData.AppendPrintf("   Pending Q Length = %" PRIuSIZE "\n",
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -139,16 +139,17 @@ nsHttpConnection::Init(nsHttpConnectionI
                        PRIntervalTime rtt)
 {
     LOG(("nsHttpConnection::Init this=%p", this));
     NS_ENSURE_ARG_POINTER(info);
     NS_ENSURE_TRUE(!mConnInfo, NS_ERROR_ALREADY_INITIALIZED);
 
     mConnectedTransport = connectedTransport;
     mConnInfo = info;
+    MOZ_DIAGNOSTIC_ASSERT(mConnInfo);
     mLastWriteTime = mLastReadTime = PR_IntervalNow();
     mRtt = rtt;
     mMaxHangTime = PR_SecondsToInterval(maxHangTime);
 
     mSocketTransport = transport;
     mSocketIn = instream;
     mSocketOut = outstream;
 
@@ -308,16 +309,17 @@ nsHttpConnection::StartSpdy(uint8_t spdy
     bool spdyProxy = mConnInfo->UsingHttpsProxy() && !mTLSFilter;
     if (spdyProxy) {
         RefPtr<nsHttpConnectionInfo> wildCardProxyCi;
         rv = mConnInfo->CreateWildCard(getter_AddRefs(wildCardProxyCi));
         MOZ_ASSERT(NS_SUCCEEDED(rv));
         gHttpHandler->ConnMgr()->MoveToWildCardConnEntry(mConnInfo,
                                                          wildCardProxyCi, this);
         mConnInfo = wildCardProxyCi;
+        MOZ_DIAGNOSTIC_ASSERT(mConnInfo);
     }
 
     if (!mDid0RTTSpdy) {
         rv = MoveTransactionsToSpdy(rv, list);
         if (NS_FAILED(rv)) {
             return;
         }
     }
@@ -1920,17 +1922,17 @@ nsHttpConnection::SetupSecondaryTLS()
 
     nsHttpConnectionInfo *ci = nullptr;
     if (mTransaction) {
         ci = mTransaction->ConnectionInfo();
     }
     if (!ci) {
         ci = mConnInfo;
     }
-    MOZ_ASSERT(ci);
+    MOZ_DIAGNOSTIC_ASSERT(ci);
 
     mTLSFilter = new TLSFilterTransaction(mTransaction,
                                           ci->Origin(), ci->OriginPort(), this, this);
 
     if (mTransaction) {
         mTransaction = mTLSFilter;
     }
 }
--- a/netwerk/protocol/http/nsHttpConnection.h
+++ b/netwerk/protocol/http/nsHttpConnection.h
@@ -218,17 +218,18 @@ public:
     // ping, ordinary HTTP connections get some time to get traffic to be
     // considered alive.
     void CheckForTraffic(bool check);
 
     // NoTraffic() returns true if there's been no traffic on the (non-spdy)
     // connection since CheckForTraffic() was called.
     bool NoTraffic() {
         return mTrafficStamp &&
-            (mTrafficCount == (mTotalBytesWritten + mTotalBytesRead));
+            (mTrafficCount == (mTotalBytesWritten + mTotalBytesRead)) &&
+            !mFastOpen;
     }
     // override of nsAHttpConnection
     virtual uint32_t Version();
 
     bool TestJoinConnection(const nsACString &hostname, int32_t port);
     bool JoinConnection(const nsACString &hostname, int32_t port);
 
     void SetFastOpenStatus(uint8_t tfoStatus) {
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -607,24 +607,25 @@ nsHttpConnectionMgr::UpdateRequestTokenB
 }
 
 nsresult
 nsHttpConnectionMgr::ClearConnectionHistory()
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-        nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+        RefPtr<nsConnectionEntry> ent = iter.Data();
         if (ent->mIdleConns.Length()    == 0 &&
             ent->mActiveConns.Length()  == 0 &&
             ent->mHalfOpens.Length()    == 0 &&
             ent->mUrgentStartQ.Length() == 0 &&
             ent->PendingQLength()       == 0 &&
             ent->mHalfOpenFastOpenBackups.Length() == 0 &&
             !ent->mDoNotDestroy) {
+            ent->mHowItWasRemoved = nsConnectionEntry::CONN_ENTRY_CLEAR_CONNECTION_HISTORY;
             iter.Remove();
         }
     }
 
     return NS_OK;
 }
 
 nsresult
@@ -633,17 +634,17 @@ nsHttpConnectionMgr::CloseIdleConnection
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     LOG(("nsHttpConnectionMgr::CloseIdleConnection %p conn=%p",
          this, conn));
 
     if (!conn->ConnectionInfo()) {
         return NS_ERROR_UNEXPECTED;
     }
 
-    nsConnectionEntry *ent = mCT.Get(conn->ConnectionInfo()->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(conn->ConnectionInfo()->HashKey());
 
     RefPtr<nsHttpConnection> deleteProtector(conn);
     if (!ent || !ent->mIdleConns.RemoveElement(conn))
         return NS_ERROR_UNEXPECTED;
 
     conn->Close(NS_ERROR_ABORT);
     mNumIdleConns--;
     ConditionallyStopPruneDeadConnectionsTimer();
@@ -657,17 +658,17 @@ nsHttpConnectionMgr::RemoveIdleConnectio
 
     LOG(("nsHttpConnectionMgr::RemoveIdleConnection %p conn=%p",
          this, conn));
 
     if (!conn->ConnectionInfo()) {
         return NS_ERROR_UNEXPECTED;
     }
 
-    nsConnectionEntry *ent = mCT.Get(conn->ConnectionInfo()->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(conn->ConnectionInfo()->HashKey());
 
     if (!ent || !ent->mIdleConns.RemoveElement(conn)) {
         return NS_ERROR_UNEXPECTED;
     }
 
     mNumIdleConns--;
     ConditionallyStopPruneDeadConnectionsTimer();
     return NS_OK;
@@ -784,17 +785,17 @@ nsHttpConnectionMgr::FindCoalescableConn
 void
 nsHttpConnectionMgr::UpdateCoalescingForNewConn(nsHttpConnection *newConn,
                                                 nsConnectionEntry *ent)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_ASSERT(newConn);
     MOZ_ASSERT(newConn->ConnectionInfo());
     MOZ_ASSERT(ent);
-    MOZ_ASSERT(mCT.Get(newConn->ConnectionInfo()->HashKey()) == ent);
+    MOZ_ASSERT(mCT.GetWeak(newConn->ConnectionInfo()->HashKey()) == ent);
 
     nsHttpConnection *existingConn = FindCoalescableConnection(ent, true);
     if (existingConn) {
         LOG(("UpdateCoalescingForNewConn() found existing active conn that could have served newConn "
              "graceful close of newConn=%p to migrate to existingConn %p\n", newConn, existingConn));
         newConn->DontReuse();
         return;
     }
@@ -817,20 +818,25 @@ nsHttpConnectionMgr::UpdateCoalescingFor
         }
         listOfWeakConns->AppendElement(
             do_GetWeakReference(static_cast<nsISupportsWeakReference*>(newConn)));
     }
 
     // Cancel any other pending connections - their associated transactions
     // are in the pending queue and will be dispatched onto this new connection
     for (int32_t index = ent->mHalfOpens.Length() - 1; index >= 0; --index) {
-        nsHalfOpenSocket *half = ent->mHalfOpens[index];
+        RefPtr<nsHalfOpenSocket> half = ent->mHalfOpens[index];
         LOG(("UpdateCoalescingForNewConn() forcing halfopen abandon %p\n",
-             half));
+             half.get()));
         ent->mHalfOpens[index]->Abandon();
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupTransport);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupStreamOut);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupStreamIn);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mSynTimer);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mEnt);
     }
 
     if (ent->mActiveConns.Length() > 1) {
         // this is a new connection that can be coalesced onto. hooray!
         // if there are other connection to this entry (e.g.
         // some could still be handshaking, shutting down, etc..) then close
         // them down after any transactions that are on them are complete.
         // This probably happened due to the parallel connection algorithm
@@ -844,17 +850,23 @@ nsHttpConnectionMgr::UpdateCoalescingFor
             }
         }
     }
 
     for (int32_t index = ent->mHalfOpenFastOpenBackups.Length() - 1; index >= 0; --index) {
         LOG(("UpdateCoalescingForNewConn() shutting down connection in fast "
              "open state (%p) because new spdy connection (%p) takes "
              "precedence\n", ent->mHalfOpenFastOpenBackups[index].get(), newConn));
-        ent->mHalfOpenFastOpenBackups[index]->CancelFastOpenConnection();
+        RefPtr<nsHalfOpenSocket> half = ent->mHalfOpenFastOpenBackups[index];
+        half->CancelFastOpenConnection();
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupTransport);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupStreamOut);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupStreamIn);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mSynTimer);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mEnt);
     }
 }
 
 // This function lets a connection, after completing the NPN phase,
 // report whether or not it is using spdy through the usingSpdy
 // argument. It would not be necessary if NPN were driven out of
 // the connection manager. The connection entry associated with the
 // connection is then updated to indicate whether or not we want to use
@@ -863,17 +875,17 @@ nsHttpConnectionMgr::UpdateCoalescingFor
 void
 nsHttpConnectionMgr::ReportSpdyConnection(nsHttpConnection *conn,
                                           bool usingSpdy)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     if (!conn->ConnectionInfo()) {
         return;
     }
-    nsConnectionEntry *ent = mCT.Get(conn->ConnectionInfo()->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(conn->ConnectionInfo()->HashKey());
     if (!ent || !usingSpdy) {
         return;
     }
 
     ent->mUsingSpdy = true;
     mNumSpdyActiveConns++;
 
     // adjust timeout timer
@@ -1164,17 +1176,17 @@ nsHttpConnectionMgr::ProcessPendingQForE
     return dispatchedSuccessfully;
 }
 
 bool
 nsHttpConnectionMgr::ProcessPendingQForEntry(nsHttpConnectionInfo *ci)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
-    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(ci->HashKey());
     if (ent)
         return ProcessPendingQForEntry(ent, false);
     return false;
 }
 
 // we're at the active connection limit if any one of the following conditions is true:
 //  (1) at max-connections
 //  (2) keep-alive enabled and at max-persistent-connections-per-server/proxy
@@ -1231,16 +1243,23 @@ nsHttpConnectionMgr::ClosePersistentConn
         ent->mIdleConns.RemoveElementAt(0);
         mNumIdleConns--;
         conn->Close(NS_ERROR_ABORT);
     }
 
     int32_t activeCount = ent->mActiveConns.Length();
     for (int32_t i=0; i < activeCount; i++)
         ent->mActiveConns[i]->DontReuse();
+    for (int32_t index = ent->mHalfOpenFastOpenBackups.Length() - 1; index >= 0; --index) {
+        RefPtr<nsHalfOpenSocket> half = ent->mHalfOpenFastOpenBackups[index];
+        half->CancelFastOpenConnection();
+        MOZ_DIAGNOSTIC_ASSERT(!half->mBackupTransport);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mSynTimer);
+        MOZ_DIAGNOSTIC_ASSERT(!half->mEnt);
+    }
 }
 
 bool
 nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
     if (ent->AvailableForDispatchNow()) {
@@ -1362,17 +1381,17 @@ nsHttpConnectionMgr::MakeNewConnection(n
 
     if ((mNumIdleConns + mNumActiveConns + 1 >= mMaxConns) && mNumIdleConns) {
         // If the global number of connections is preventing the opening of new
         // connections to a host without idle connections, then close them
         // regardless of their TTL.
         auto iter = mCT.Iter();
         while (mNumIdleConns + mNumActiveConns + 1 >= mMaxConns &&
                !iter.Done()) {
-            nsAutoPtr<nsConnectionEntry> &entry = iter.Data();
+            RefPtr<nsConnectionEntry> entry = iter.Data();
             if (!entry->mIdleConns.Length()) {
               iter.Next();
               continue;
             }
             RefPtr<nsHttpConnection> conn(entry->mIdleConns[0]);
             entry->mIdleConns.RemoveElementAt(0);
             conn->Close(NS_ERROR_ABORT);
             mNumIdleConns--;
@@ -1382,17 +1401,17 @@ nsHttpConnectionMgr::MakeNewConnection(n
 
     if ((mNumIdleConns + mNumActiveConns + 1 >= mMaxConns) &&
         mNumActiveConns && gHttpHandler->IsSpdyEnabled())
     {
         // If the global number of connections is preventing the opening of new
         // connections to a host without idle connections, then close any spdy
         // ASAP.
         for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-            nsAutoPtr<nsConnectionEntry> &entry = iter.Data();
+            RefPtr<nsConnectionEntry> entry = iter.Data();
             if (!entry->mUsingSpdy) {
                 continue;
             }
 
             for (uint32_t index = 0;
                  index < entry->mActiveConns.Length();
                  ++index) {
                 nsHttpConnection *conn = entry->mActiveConns[index];
@@ -1714,16 +1733,17 @@ NS_IMPL_ISUPPORTS0(ConnectionHandle)
 // concrete nsHttpTransaction
 nsresult
 nsHttpConnectionMgr::DispatchAbstractTransaction(nsConnectionEntry *ent,
                                                  nsAHttpTransaction *aTrans,
                                                  uint32_t caps,
                                                  nsHttpConnection *conn,
                                                  int32_t priority)
 {
+    MOZ_DIAGNOSTIC_ASSERT(ent);
     nsresult rv;
     MOZ_ASSERT(!conn->UsingSpdy(),
                "Spdy Must Not Use DispatchAbstractTransaction");
     LOG(("nsHttpConnectionMgr::DispatchAbstractTransaction "
          "[ci=%s trans=%p caps=%x conn=%p]\n",
          ent->mConnInfo->HashKey().get(), aTrans, caps, conn));
 
     RefPtr<nsAHttpTransaction> transaction(aTrans);
@@ -1789,16 +1809,17 @@ nsHttpConnectionMgr::ProcessNewTransacti
     }
 
     nsresult rv = NS_OK;
     nsHttpConnectionInfo *ci = trans->ConnectionInfo();
     MOZ_ASSERT(ci);
 
     nsConnectionEntry *ent =
         GetOrCreateConnectionEntry(ci, !!trans->TunnelProvider());
+    MOZ_DIAGNOSTIC_ASSERT(ent);
 
     ReportProxyTelemetry(ent);
 
     // Check if the transaction already has a sticky reference to a connection.
     // If so, then we can just use it directly by transferring its reference
     // to the new connection variable instead of searching for a new one
 
     nsAHttpConnection *wrappedConnection = trans->Connection();
@@ -2038,17 +2059,17 @@ nsHttpConnectionMgr::ProcessSpdyPendingQ
 }
 
 void
 nsHttpConnectionMgr::OnMsgProcessAllSpdyPendingQ(int32_t, ARefBase *)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     LOG(("nsHttpConnectionMgr::OnMsgProcessAllSpdyPendingQ\n"));
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-        ProcessSpdyPendingQ(iter.Data());
+        ProcessSpdyPendingQ(iter.Data().get());
     }
 }
 
 // Given a connection entry, return an active h2 connection
 // that can be directly activated or null
 nsHttpConnection *
 nsHttpConnectionMgr::GetSpdyActiveConn(nsConnectionEntry *ent)
 {
@@ -2083,17 +2104,24 @@ nsHttpConnectionMgr::GetSpdyActiveConn(n
                 tmp->DontReuse();
             }
         }
         for (int32_t index = ent->mHalfOpenFastOpenBackups.Length() - 1; index >= 0; --index) {
              LOG(("GetSpdyActiveConn() shutting down connection in fast "
                  "open state (%p) because we have an experienced spdy "
                  "connection (%p).\n",
                  ent->mHalfOpenFastOpenBackups[index].get(), experienced));
-             ent->mHalfOpenFastOpenBackups[index]->CancelFastOpenConnection();
+             RefPtr<nsHalfOpenSocket> half = ent->mHalfOpenFastOpenBackups[index];
+             half->CancelFastOpenConnection();
+
+             MOZ_DIAGNOSTIC_ASSERT(!half->mBackupTransport);
+             MOZ_DIAGNOSTIC_ASSERT(!half->mBackupStreamOut);
+             MOZ_DIAGNOSTIC_ASSERT(!half->mBackupStreamIn);
+             MOZ_DIAGNOSTIC_ASSERT(!half->mSynTimer);
+             MOZ_DIAGNOSTIC_ASSERT(!half->mEnt);
         }
 
         LOG(("GetSpdyActiveConn() request for ent %p %s "
              "found an active experienced connection %p in native connection entry\n",
              ent, ci->HashKey().get(), experienced));
         return experienced;
     }
 
@@ -2125,17 +2153,17 @@ void
 nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     LOG(("nsHttpConnectionMgr::OnMsgShutdown\n"));
 
     gHttpHandler->StopRequestTokenBucket();
 
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-        nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+        RefPtr<nsConnectionEntry> ent = iter.Data();
 
         // Close all active connections.
         while (ent->mActiveConns.Length()) {
             RefPtr<nsHttpConnection> conn(ent->mActiveConns[0]);
             ent->mActiveConns.RemoveElementAt(0);
             DecrementActiveConnCount(conn);
             // Since nsHttpConnection::Close doesn't break the bond with
             // the connection's transaction, we must explicitely tell it
@@ -2178,16 +2206,17 @@ nsHttpConnectionMgr::OnMsgShutdown(int32
 
         // Close all half open tcp connections.
         for (int32_t i = int32_t(ent->mHalfOpens.Length()) - 1; i >= 0; i--) {
             ent->mHalfOpens[i]->Abandon();
         }
 
         MOZ_DIAGNOSTIC_ASSERT(ent->mHalfOpenFastOpenBackups.Length() == 0 &&
                               !ent->mDoNotDestroy);
+        ent->mHowItWasRemoved = nsConnectionEntry::CONN_ENTRY_REMOVED_SHUTDOWN;
         iter.Remove();
     }
 
     if (mTimeoutTick) {
         mTimeoutTick->Cancel();
         mTimeoutTick = nullptr;
         mTimeoutTickArmed = false;
     }
@@ -2241,17 +2270,17 @@ nsHttpConnectionMgr::OnMsgReschedTransac
     LOG(("nsHttpConnectionMgr::OnMsgReschedTransaction [trans=%p]\n", param));
 
     RefPtr<nsHttpTransaction> trans = static_cast<nsHttpTransaction *>(param);
     trans->SetPriority(priority);
 
     if (!trans->ConnectionInfo()) {
         return;
     }
-    nsConnectionEntry *ent = mCT.Get(trans->ConnectionInfo()->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(trans->ConnectionInfo()->HashKey());
 
     if (ent) {
         int32_t caps = trans->Caps();
         nsTArray<RefPtr<PendingTransactionInfo>> *pendingQ = nullptr;
         if (caps & NS_HTTP_URGENT_START) {
             pendingQ = &(ent->mUrgentStartQ);
         } else {
             pendingQ =
@@ -2303,17 +2332,17 @@ nsHttpConnectionMgr::OnMsgCancelTransact
     // transaction directly (removing it from the pending queue first).
     //
     RefPtr<nsAHttpConnection> conn(trans->Connection());
     if (conn && !trans->IsDone()) {
         conn->CloseTransaction(trans, closeCode);
     } else {
         nsConnectionEntry *ent = nullptr;
         if (trans->ConnectionInfo()) {
-            ent = mCT.Get(trans->ConnectionInfo()->HashKey());
+            ent = mCT.GetWeak(trans->ConnectionInfo()->HashKey());
         }
         if (ent) {
             uint32_t caps = trans->Caps();
             int32_t transIndex;
             // We will abandon all half-open sockets belonging to the given
             // transaction.
             nsTArray<RefPtr<PendingTransactionInfo>> *infoArray;
             RefPtr<PendingTransactionInfo> pendingTransInfo;
@@ -2375,31 +2404,31 @@ nsHttpConnectionMgr::OnMsgProcessPending
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     nsHttpConnectionInfo *ci = static_cast<nsHttpConnectionInfo *>(param);
 
     if (!ci) {
         LOG(("nsHttpConnectionMgr::OnMsgProcessPendingQ [ci=nullptr]\n"));
         // Try and dispatch everything
         for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-            Unused << ProcessPendingQForEntry(iter.Data(), true);
+            Unused << ProcessPendingQForEntry(iter.Data().get(), true);
         }
         return;
     }
 
     LOG(("nsHttpConnectionMgr::OnMsgProcessPendingQ [ci=%s]\n",
          ci->HashKey().get()));
 
     // start by processing the queue identified by the given connection info.
-    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(ci->HashKey());
     if (!(ent && ProcessPendingQForEntry(ent, false))) {
         // if we reach here, it means that we couldn't dispatch a transaction
         // for the specified connection info.  walk the connection table...
         for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-            if (ProcessPendingQForEntry(iter.Data(), false)) {
+            if (ProcessPendingQForEntry(iter.Data().get(), false)) {
                 break;
             }
         }
     }
 }
 
 nsresult
 nsHttpConnectionMgr::CancelTransactions(nsHttpConnectionInfo *ci, nsresult code)
@@ -2425,17 +2454,17 @@ nsHttpConnectionMgr::CancelTransactionsH
     pendingQ.Clear();
 }
 
 void
 nsHttpConnectionMgr::OnMsgCancelTransactions(int32_t code, ARefBase *param)
 {
     nsresult reason = static_cast<nsresult>(code);
     nsHttpConnectionInfo *ci = static_cast<nsHttpConnectionInfo *>(param);
-    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(ci->HashKey());
     LOG(("nsHttpConnectionMgr::OnMsgCancelTransactions %s %p\n",
          ci->HashKey().get(), ent));
     if (!ent) {
         return;
     }
 
     CancelTransactionsHelper(ent->mUrgentStartQ, ci, ent, reason);
 
@@ -2455,17 +2484,17 @@ nsHttpConnectionMgr::OnMsgPruneDeadConne
 
     // Reset mTimeOfNextWakeUp so that we can find a new shortest value.
     mTimeOfNextWakeUp = UINT64_MAX;
 
     // check canreuse() for all idle connections plus any active connections on
     // connection entries that are using spdy.
     if (mNumIdleConns || (mNumActiveConns && gHttpHandler->IsSpdyEnabled())) {
         for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-            nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+            RefPtr<nsConnectionEntry> ent = iter.Data();
 
             LOG(("  pruning [ci=%s]\n", ent->mConnInfo->HashKey().get()));
 
             // Find out how long it will take for next idle connection to not
             // be reusable anymore.
             uint32_t timeToNextExpire = UINT32_MAX;
             int32_t count = ent->mIdleConns.Length();
             if (count > 0) {
@@ -2551,17 +2580,17 @@ nsHttpConnectionMgr::OnMsgPruneNoTraffic
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     LOG(("nsHttpConnectionMgr::OnMsgPruneNoTraffic\n"));
 
     // Prune connections without traffic
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
 
         // Close the connections with no registered traffic.
-        nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+        RefPtr<nsConnectionEntry> ent = iter.Data();
 
         LOG(("  pruning no traffic [ci=%s]\n",
              ent->mConnInfo->HashKey().get()));
 
         uint32_t numConns = ent->mActiveConns.Length();
         if (numConns) {
             // Walk the list backwards to allow us to remove entries easily.
             for (int index = numConns - 1; index >= 0; index--) {
@@ -2589,17 +2618,17 @@ nsHttpConnectionMgr::OnMsgVerifyTraffic(
     if (mPruningNoTraffic) {
       // Called in the time gap when the timeout to prune notraffic
       // connections has triggered but the pruning hasn't happened yet.
       return;
     }
 
     // Mark connections for traffic verification
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-        nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+        RefPtr<nsConnectionEntry> ent = iter.Data();
 
         // Iterate over all active connections and check them.
         for (uint32_t index = 0; index < ent->mActiveConns.Length(); ++index) {
             ent->mActiveConns[index]->CheckForTraffic(true);
         }
         // Iterate the idle connections and unmark them for traffic checks.
         for (uint32_t index = 0; index < ent->mIdleConns.Length(); ++index) {
             ent->mIdleConns[index]->CheckForTraffic(false);
@@ -2647,18 +2676,19 @@ nsHttpConnectionMgr::OnMsgReclaimConnect
     nsHttpConnection *conn = static_cast<nsHttpConnection *>(param);
 
     //
     // 1) remove the connection from the active list
     // 2) if keep-alive, add connection to idle list
     // 3) post event to process the pending transaction queue
     //
 
+    MOZ_DIAGNOSTIC_ASSERT(conn);
     nsConnectionEntry *ent = conn->ConnectionInfo() ?
-        mCT.Get(conn->ConnectionInfo()->HashKey()) : nullptr;
+        mCT.GetWeak(conn->ConnectionInfo()->HashKey()) : nullptr;
 
     if (!ent) {
         // this can happen if the connection is made outside of the
         // connection manager and is being "reclaimed" for use with
         // future transactions. HTTP/2 tunnels work like this.
         ent = GetOrCreateConnectionEntry(conn->ConnectionInfo(), true);
         LOG(("nsHttpConnectionMgr::OnMsgReclaimConnection conn %p "
              "forced new hash entry %s\n",
@@ -3114,17 +3144,17 @@ nsHttpConnectionMgr::ShouldStopReading(n
     }
 
     // There are only unthrottled transactions for background tabs: don't throttle.
     return false;
 }
 
 bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo)
 {
-    nsConnectionEntry *ent = mCT.Get(connInfo->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(connInfo->HashKey());
     if (!ent) {
       // No entry, no pressure.
       return false;
     }
 
     nsTArray<RefPtr<PendingTransactionInfo>> *transactions =
         ent->mPendingTransactionTable.Get(mCurrentTopLevelOuterContentWindowId);
 
@@ -3386,17 +3416,17 @@ nsHttpConnectionMgr::TimeoutTick()
 
     LOG(("nsHttpConnectionMgr::TimeoutTick active=%d\n", mNumActiveConns));
     // The next tick will be between 1 second and 1 hr
     // Set it to the max value here, and the TimeoutTick()s can
     // reduce it to their local needs.
     mTimeoutTickNext = 3600; // 1hr
 
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-        nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+        RefPtr<nsConnectionEntry> ent = iter.Data();
 
         LOG(("nsHttpConnectionMgr::TimeoutTick() this=%p host=%s "
              "idle=%" PRIuSIZE " active=%" PRIuSIZE
              " half-len=%" PRIuSIZE " pending=%" PRIuSIZE
              " urgentStart pending=%" PRIuSIZE "\n",
              this, ent->mConnInfo->Origin(), ent->mIdleConns.Length(),
              ent->mActiveConns.Length(), ent->mHalfOpens.Length(),
              ent->PendingQLength(), ent->mUrgentStartQ.Length()));
@@ -3458,31 +3488,31 @@ nsHttpConnectionMgr::TimeoutTick()
 // 2] otherwise use an ent of wildcard(ci) than can be dispatched immediately
 // 3] otherwise create an ent that matches ci and make new conn on it
 
 nsHttpConnectionMgr::nsConnectionEntry *
 nsHttpConnectionMgr::GetOrCreateConnectionEntry(nsHttpConnectionInfo *specificCI,
                                                 bool prohibitWildCard)
 {
     // step 1
-    nsConnectionEntry *specificEnt = mCT.Get(specificCI->HashKey());
+    nsConnectionEntry *specificEnt = mCT.GetWeak(specificCI->HashKey());
     if (specificEnt && specificEnt->AvailableForDispatchNow()) {
         return specificEnt;
     }
 
     if (!specificCI->UsingHttpsProxy()) {
         prohibitWildCard = true;
     }
 
     // step 2
     if (!prohibitWildCard) {
         RefPtr<nsHttpConnectionInfo> wildCardProxyCI;
         DebugOnly<nsresult> rv = specificCI->CreateWildCard(getter_AddRefs(wildCardProxyCI));
         MOZ_ASSERT(NS_SUCCEEDED(rv));
-        nsConnectionEntry *wildCardEnt = mCT.Get(wildCardProxyCI->HashKey());
+        nsConnectionEntry *wildCardEnt = mCT.GetWeak(wildCardProxyCI->HashKey());
         if (wildCardEnt && wildCardEnt->AvailableForDispatchNow()) {
             return wildCardEnt;
         }
     }
 
     // step 3
     if (!specificEnt) {
         RefPtr<nsHttpConnectionInfo> clone(specificCI->Clone());
@@ -3603,65 +3633,68 @@ NS_INTERFACE_MAP_BEGIN(nsHttpConnectionM
 NS_INTERFACE_MAP_END
 
 nsHttpConnectionMgr::
 nsHalfOpenSocket::nsHalfOpenSocket(nsConnectionEntry *ent,
                                    nsAHttpTransaction *trans,
                                    uint32_t caps,
                                    bool speculative,
                                    bool isFromPredictor)
-    : mEnt(ent)
-    , mTransaction(trans)
+    : mTransaction(trans)
     , mDispatchedMTransaction(false)
     , mCaps(caps)
     , mSpeculative(speculative)
     , mIsFromPredictor(isFromPredictor)
     , mAllow1918(true)
     , mHasConnected(false)
     , mPrimaryConnectedOK(false)
     , mBackupConnectedOK(false)
     , mFreeToUse(true)
     , mPrimaryStreamStatus(NS_OK)
     , mFastOpenInProgress(false)
+    , mEnt(ent)
 {
     MOZ_ASSERT(ent && trans, "constructor with null arguments");
     LOG(("Creating nsHalfOpenSocket [this=%p trans=%p ent=%s key=%s]\n",
          this, trans, ent->mConnInfo->Origin(), ent->mConnInfo->HashKey().get()));
 
     if (speculative) {
         Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_TOTAL_SPECULATIVE_CONN> totalSpeculativeConn;
         ++totalSpeculativeConn;
 
         if (isFromPredictor) {
           Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS_CREATED> totalPreconnectsCreated;
           ++totalPreconnectsCreated;
         }
     }
+
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
 }
 
 nsHttpConnectionMgr::nsHalfOpenSocket::~nsHalfOpenSocket()
 {
-    MOZ_ASSERT(!mStreamOut);
-    MOZ_ASSERT(!mBackupStreamOut);
-    MOZ_ASSERT(!mSynTimer);
+    MOZ_DIAGNOSTIC_ASSERT(!mStreamOut);
+    MOZ_DIAGNOSTIC_ASSERT(!mBackupStreamOut);
+    MOZ_DIAGNOSTIC_ASSERT(!mSynTimer);
     LOG(("Destroying nsHalfOpenSocket [this=%p]\n", this));
 
     if (mEnt)
         mEnt->RemoveHalfOpen(this);
 }
 
 nsresult
 nsHttpConnectionMgr::
 nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport,
                                nsIAsyncInputStream **instream,
                                nsIAsyncOutputStream **outstream,
                                bool isBackup)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
     nsresult rv;
     const char *socketTypes[1];
     uint32_t typeCount = 0;
     const nsHttpConnectionInfo *ci = mEnt->mConnInfo;
     if (ci->FirstHopSSL()) {
         socketTypes[typeCount++] = "ssl";
     } else {
         socketTypes[typeCount] = gHttpHandler->DefaultSocketType();
@@ -3836,18 +3869,19 @@ nsHttpConnectionMgr::nsHalfOpenSocket::S
         mBackupTransport = nullptr;
     }
     return rv;
 }
 
 void
 nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupTimer()
 {
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
     uint16_t timeout = gHttpHandler->GetIdleSynTimeout();
-    MOZ_ASSERT(!mSynTimer, "timer already initd");
+    MOZ_DIAGNOSTIC_ASSERT(!mSynTimer, "timer already initd");
     if (!timeout && mFastOpenInProgress) {
         timeout = 250;
     }
     // When using Fast Open the correct transport will be setup for sure (it is
     // guaranteed), but it can be that it will happened a bit later.
     if (mFastOpenInProgress ||
         (timeout && !mSpeculative)) {
         // Setup the timer that will establish a backup socket
@@ -3918,17 +3952,24 @@ nsHttpConnectionMgr::nsHalfOpenSocket::A
     }
     if (mBackupStreamOut) {
         gHttpHandler->ConnMgr()->RecvdConnect();
         mBackupStreamOut->AsyncWait(nullptr, 0, 0, nullptr);
         mBackupStreamOut = nullptr;
     }
 
     // Lose references to input stream (and backup).
-    mStreamIn = mBackupStreamIn = nullptr;
+    if (mStreamIn) {
+        mStreamIn->AsyncWait(nullptr, 0, 0, nullptr);
+        mStreamIn = nullptr;
+    }
+    if (mBackupStreamIn) {
+        mBackupStreamIn->AsyncWait(nullptr, 0, 0, nullptr);
+        mBackupStreamIn = nullptr;
+    }
 
     // Stop the timer - we don't want any new backups.
     CancelBackupTimer();
 
     // Remove the half open from the connection entry.
     if (mEnt) {
         mEnt->mDoNotDestroy = false;
         mEnt->RemoveHalfOpen(this);
@@ -3945,17 +3986,21 @@ nsHttpConnectionMgr::nsHalfOpenSocket::D
     return (epoch - mPrimarySynStarted).ToMilliseconds();
 }
 
 
 NS_IMETHODIMP // method for nsITimerCallback
 nsHttpConnectionMgr::nsHalfOpenSocket::Notify(nsITimer *timer)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
-    MOZ_ASSERT(timer == mSynTimer, "wrong timer");
+    MOZ_DIAGNOSTIC_ASSERT(timer == mSynTimer, "wrong timer");
+
+    MOZ_DIAGNOSTIC_ASSERT(!mBackupTransport);
+    MOZ_DIAGNOSTIC_ASSERT(mSynTimer);
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
 
     DebugOnly<nsresult> rv = SetupBackupStreams();
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     mSynTimer = nullptr;
     return NS_OK;
 }
 
@@ -3988,18 +4033,21 @@ nsHalfOpenSocket::FindTransactionHelper(
 }
 
 // method for nsIAsyncOutputStreamCallback
 NS_IMETHODIMP
 nsHttpConnectionMgr::
 nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
-    MOZ_ASSERT(out == mStreamOut || out == mBackupStreamOut,
-               "stream mismatch");
+    MOZ_DIAGNOSTIC_ASSERT(mStreamOut || mBackupStreamOut);
+    MOZ_DIAGNOSTIC_ASSERT(out == mStreamOut || out == mBackupStreamOut,
+                          "stream mismatch");
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
+
     LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n",
          this, mEnt->mConnInfo->Origin(),
          out == mStreamOut ? "primary" : "backup"));
 
     mEnt->mDoNotDestroy = true;
     gHttpHandler->ConnMgr()->RecvdConnect();
 
     CancelBackupTimer();
@@ -4111,18 +4159,19 @@ nsHalfOpenSocket::FastOpenEnabled()
 
     return true;
 }
 
 nsresult
 nsHttpConnectionMgr::
 nsHalfOpenSocket::StartFastOpen()
 {
-    MOZ_ASSERT(mStreamOut);
-    MOZ_ASSERT(mEnt && !mBackupTransport);
+    MOZ_DIAGNOSTIC_ASSERT(mStreamOut);
+    MOZ_DIAGNOSTIC_ASSERT(!mBackupTransport);
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
 
     LOG(("nsHalfOpenSocket::StartFastOpen [this=%p]\n",
          this));
 
     RefPtr<nsHalfOpenSocket> deleteProtector(this);
 
     mFastOpenInProgress = true;
     // Remove this HalfOpen from mEnt->mHalfOpens.
@@ -4191,17 +4240,18 @@ nsHalfOpenSocket::StartFastOpen()
     }
     return rv;
 }
 
 void
 nsHttpConnectionMgr::
 nsHalfOpenSocket::SetFastOpenConnected(nsresult aError, bool aWillRetry)
 {
-    MOZ_ASSERT(mFastOpenInProgress);
+    MOZ_DIAGNOSTIC_ASSERT(mFastOpenInProgress);
+    MOZ_DIAGNOSTIC_ASSERT(mEnt);
 
     LOG(("nsHalfOpenSocket::SetFastOpenConnected [this=%p conn=%p error=%x]\n",
          this, mConnectionNegotiatingFastOpen.get(),
          static_cast<uint32_t>(aError)));
 
     // mConnectionNegotiatingFastOpen is set after a StartFastOpen creates
     // and activates a nsHttpConnection successfully (SetupConn calls
     // DispatchTransaction and DispatchAbstractTransaction which calls
@@ -4261,60 +4311,62 @@ nsHalfOpenSocket::SetFastOpenConnected(n
         mEnt->mHalfOpens.AppendElement(this);
         gHttpHandler->ConnMgr()->mNumHalfOpenConns++;
         gHttpHandler->ConnMgr()->StartedConnect();
 
         // Restore callbacks.
         mStreamOut->AsyncWait(this, 0, 0, nullptr);
         mSocketTransport->SetEventSink(this, nullptr);
         mSocketTransport->SetSecurityCallbacks(this);
-        mStreamOut->AsyncWait(this, 0, 0, nullptr);
+        mStreamIn->AsyncWait(nullptr, 0, 0, nullptr);
 
     } else {
         // On success or other error we proceed with connection, we just need
         // to close backup timer and halfOpenSock.
         CancelBackupTimer();
         if (NS_SUCCEEDED(aError)) {
             NetAddr peeraddr;
             if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) {
                 mEnt->RecordIPFamilyPreference(peeraddr.raw.family);
             }
             gHttpHandler->ResetFastOpenConsecutiveFailureCounter();
         }
         mSocketTransport = nullptr;
         mStreamOut = nullptr;
         mStreamIn = nullptr;
 
-        // If backup transport ha already started put this HalfOpen back to
-        // mEnt list.
-        if (mBackupTransport) {
-            mEnt->mHalfOpens.AppendElement(this);
-            gHttpHandler->ConnMgr()->mNumHalfOpenConns++;
-        }
+        Abandon();
     }
 
     mFastOpenInProgress = false;
     mConnectionNegotiatingFastOpen = nullptr;
-    mEnt->mDoNotDestroy = false;
+    if (mEnt) {
+        mEnt->mDoNotDestroy = false;
+        MOZ_DIAGNOSTIC_ASSERT(mEnt->mHalfOpens.Contains(this));
+    } else {
+        MOZ_DIAGNOSTIC_ASSERT(!mSynTimer);
+        MOZ_DIAGNOSTIC_ASSERT(!mBackupTransport);
+        MOZ_DIAGNOSTIC_ASSERT(!mBackupStreamOut);
+    }
 }
 
 void
 nsHttpConnectionMgr::
 nsHalfOpenSocket::SetFastOpenStatus(uint8_t tfoStatus)
 {
     MOZ_ASSERT(mFastOpenInProgress);
     mConnectionNegotiatingFastOpen->SetFastOpenStatus(tfoStatus);
     mConnectionNegotiatingFastOpen->Transaction()->SetFastOpenStatus(tfoStatus);
 }
 
 void
 nsHttpConnectionMgr::
 nsHalfOpenSocket::CancelFastOpenConnection()
 {
-    MOZ_ASSERT(mFastOpenInProgress);
+    MOZ_DIAGNOSTIC_ASSERT(mFastOpenInProgress);
 
     LOG(("nsHalfOpenSocket::CancelFastOpenConnection [this=%p conn=%p]\n",
          this, mConnectionNegotiatingFastOpen.get()));
 
     RefPtr<nsHalfOpenSocket> deleteProtector(this);
     mEnt->mHalfOpenFastOpenBackups.RemoveElement(this);
     mSocketTransport->SetFastOpenCallback(nullptr);
     mConnectionNegotiatingFastOpen->SetFastOpen(false);
@@ -4334,16 +4386,19 @@ nsHalfOpenSocket::CancelFastOpenConnecti
         } else {
             mEnt->InsertTransaction(pendingTransInfo, true);
         }
     }
 
     mFastOpenInProgress = false;
     mConnectionNegotiatingFastOpen = nullptr;
     Abandon();
+    MOZ_DIAGNOSTIC_ASSERT(!mSynTimer);
+    MOZ_DIAGNOSTIC_ASSERT(!mBackupTransport);
+    MOZ_DIAGNOSTIC_ASSERT(!mBackupStreamOut);
 }
 
 void
 nsHttpConnectionMgr::
 nsHalfOpenSocket::FastOpenNotSupported()
 {
   MOZ_ASSERT(mFastOpenInProgress);
   gHttpHandler->SetFastOpenNotSupported();
@@ -4506,18 +4561,18 @@ nsHalfOpenSocket::SetupConn(nsIAsyncOutp
                 }
             }
         }
     }
 
     // If this connection has a transaction get reference to its
     // ConnectionHandler.
     if (aFastOpen) {
-        MOZ_ASSERT(mEnt);
-        MOZ_ASSERT(static_cast<int32_t>(mEnt->mIdleConns.IndexOf(conn)) == -1);
+        MOZ_DIAGNOSTIC_ASSERT(mEnt);
+        MOZ_DIAGNOSTIC_ASSERT(static_cast<int32_t>(mEnt->mIdleConns.IndexOf(conn)) == -1);
         int32_t idx = mEnt->mActiveConns.IndexOf(conn);
         if (NS_SUCCEEDED(rv) && (idx != -1)) {
             mConnectionNegotiatingFastOpen = conn;
         } else {
             conn->SetFastOpen(false);
         }
     }
 
@@ -4561,17 +4616,24 @@ nsHttpConnectionMgr::RegisterOriginCoale
 NS_IMETHODIMP
 nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans,
                                                          nsresult status,
                                                          int64_t progress,
                                                          int64_t progressMax)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
+    MOZ_DIAGNOSTIC_ASSERT((trans == mSocketTransport) || (trans == mBackupTransport));
     MOZ_DIAGNOSTIC_ASSERT(mEnt);
+
+    if (mEnt->mHowItWasRemoved == nsConnectionEntry::CONN_ENTRY_CLEAR_CONNECTION_HISTORY) {
+        MOZ_DIAGNOSTIC_ASSERT(false);
+    } else if (mEnt->mHowItWasRemoved == nsConnectionEntry::CONN_ENTRY_REMOVED_SHUTDOWN) {
+        MOZ_DIAGNOSTIC_ASSERT(false);
+    }
     if (mTransaction) {
         RefPtr<PendingTransactionInfo> info = FindTransactionHelper(false);
         if ((trans == mSocketTransport) ||
             ((trans == mBackupTransport) && (status == NS_NET_STATUS_CONNECTED_TO) &&
             info)) {
             // Send this status event only if the transaction is still panding,
             // i.e. it has not found a free already connected socket.
             // Sockets in halfOpen state can only get following events:
@@ -4748,16 +4810,17 @@ ConnectionHandle::HttpConnection()
 nsHttpConnectionMgr::
 nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci)
     : mConnInfo(ci)
     , mUsingSpdy(false)
     , mPreferIPv4(false)
     , mPreferIPv6(false)
     , mUsedForConnection(false)
     , mDoNotDestroy(false)
+    , mHowItWasRemoved(CONN_ENTRY_NOT_REMOVED)
 {
     MOZ_COUNT_CTOR(nsConnectionEntry);
     mUseFastOpen = gHttpHandler->UseFastOpen();
 
     LOG(("nsConnectionEntry::nsConnectionEntry this=%p key=%s",
          this, ci->HashKey().get()));
 }
 
@@ -4771,17 +4834,17 @@ nsHttpConnectionMgr::nsConnectionEntry::
     return gHttpHandler->ConnMgr()->
         GetSpdyActiveConn(this) ? true : false;
 }
 
 bool
 nsHttpConnectionMgr::GetConnectionData(nsTArray<HttpRetParams> *aArg)
 {
     for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
-        nsAutoPtr<nsConnectionEntry>& ent = iter.Data();
+        RefPtr<nsConnectionEntry> ent = iter.Data();
 
         if (ent->mConnInfo->GetPrivate()) {
             continue;
         }
 
         HttpRetParams data;
         data.host = ent->mConnInfo->Origin();
         data.port = ent->mConnInfo->OriginPort();
@@ -4818,17 +4881,17 @@ nsHttpConnectionMgr::GetConnectionData(n
 
     return true;
 }
 
 void
 nsHttpConnectionMgr::ResetIPFamilyPreference(nsHttpConnectionInfo *ci)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
-    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(ci->HashKey());
     if (ent) {
         ent->ResetIPFamilyPreference();
     }
 }
 
 uint32_t
 nsHttpConnectionMgr::
 nsConnectionEntry::UnconnectedHalfOpens()
@@ -5016,17 +5079,17 @@ nsHttpConnectionMgr::MoveToWildCardConnE
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_ASSERT(specificCI->UsingHttpsProxy());
 
     LOG(("nsHttpConnectionMgr::MakeConnEntryWildCard conn %p has requested to "
          "change CI from %s to %s\n", proxyConn, specificCI->HashKey().get(),
          wildCardCI->HashKey().get()));
 
-    nsConnectionEntry *ent = mCT.Get(specificCI->HashKey());
+    nsConnectionEntry *ent = mCT.GetWeak(specificCI->HashKey());
     LOG(("nsHttpConnectionMgr::MakeConnEntryWildCard conn %p using ent %p (spdy %d)\n",
          proxyConn, ent, ent ? ent->mUsingSpdy : 0));
 
     if (!ent || !ent->mUsingSpdy) {
         return;
     }
 
     nsConnectionEntry *wcEnt = GetOrCreateConnectionEntry(wildCardCI, true);
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -239,22 +239,21 @@ private:
     class PendingTransactionInfo;
 
     // nsConnectionEntry
     //
     // mCT maps connection info hash key to nsConnectionEntry object, which
     // contains list of active and idle connections as well as the list of
     // pending transactions.
     //
-    class nsConnectionEntry : public SupportsWeakPtr<nsConnectionEntry>
+    class nsConnectionEntry
     {
     public:
-        MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsConnectionEntry)
+        NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsConnectionEntry)
         explicit nsConnectionEntry(nsHttpConnectionInfo *ci);
-        ~nsConnectionEntry();
 
         RefPtr<nsHttpConnectionInfo> mConnInfo;
         nsTArray<RefPtr<PendingTransactionInfo> > mUrgentStartQ;// the urgent start transaction queue
 
         // This table provides a mapping from top level outer content window id
         // to a queue of pending transaction information.
         // The transaction's order in pending queue is decided by whether it's a
         // blocking transaction and its priority.
@@ -332,16 +331,23 @@ private:
         // focused and non-focused windows.
         void AppendPendingQForNonFocusedWindows(
             uint64_t windowId,
             nsTArray<RefPtr<PendingTransactionInfo>> &result,
             uint32_t maxCount = 0);
 
         // Remove the empty pendingQ in |mPendingTransactionTable|.
         void RemoveEmptyPendingQ();
+        enum {
+          CONN_ENTRY_NOT_REMOVED,
+          CONN_ENTRY_CLEAR_CONNECTION_HISTORY,
+          CONN_ENTRY_REMOVED_SHUTDOWN,
+        }  mHowItWasRemoved;
+    private:
+        ~nsConnectionEntry();
     };
 
 public:
     static nsAHttpConnection *MakeConnectionHandle(nsHttpConnection *aWrapped);
     void RegisterOriginCoalescingKey(nsHttpConnection *, const nsACString &host, int32_t port);
 
 private:
 
@@ -401,27 +407,27 @@ private:
         void Unclaim();
 
         bool FastOpenEnabled() override;
         nsresult StartFastOpen() override;
         void SetFastOpenConnected(nsresult, bool aWillRetry) override;
         void FastOpenNotSupported() override;
         void SetFastOpenStatus(uint8_t tfoStatus) override;
         void CancelFastOpenConnection();
+
     private:
         nsresult SetupConn(nsIAsyncOutputStream *out,
                            bool aFastOpen);
 
         // To find out whether |mTransaction| is still in the connection entry's
         // pending queue. If the transaction is found and |removeWhenFound| is
         // true, the transaction will be removed from the pending queue.
         already_AddRefed<PendingTransactionInfo>
         FindTransactionHelper(bool removeWhenFound);
 
-        WeakPtr<nsConnectionEntry>     mEnt;
         RefPtr<nsAHttpTransaction>     mTransaction;
         bool                           mDispatchedMTransaction;
         nsCOMPtr<nsISocketTransport>   mSocketTransport;
         nsCOMPtr<nsIAsyncOutputStream> mStreamOut;
         nsCOMPtr<nsIAsyncInputStream>  mStreamIn;
         uint32_t                       mCaps;
 
         // mSpeculative is set if the socket was created from
@@ -438,38 +444,44 @@ private:
         // connections from the predictor.
         bool                           mIsFromPredictor;
 
         bool                           mAllow1918;
 
         TimeStamp             mPrimarySynStarted;
         TimeStamp             mBackupSynStarted;
 
-        // for syn retry
-        nsCOMPtr<nsITimer>             mSynTimer;
-        nsCOMPtr<nsISocketTransport>   mBackupTransport;
-        nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut;
-        nsCOMPtr<nsIAsyncInputStream>  mBackupStreamIn;
-
         // mHasConnected tracks whether one of the sockets has completed the
         // connection process. It may have completed unsuccessfully.
         bool                           mHasConnected;
 
         bool                           mPrimaryConnectedOK;
         bool                           mBackupConnectedOK;
 
         // A nsHalfOpenSocket can be made for a concrete non-null transaction,
         // but the transaction can be dispatch to another connection. In that
         // case we can free this transaction to be claimed by other
         // transactions.
         bool                           mFreeToUse;
         nsresult                       mPrimaryStreamStatus;
 
         bool                           mFastOpenInProgress;
         RefPtr<nsHttpConnection>       mConnectionNegotiatingFastOpen;
+
+    private:
+        // nsHttpConnectionMgr is friend class so that we can access them for
+        // diagnostic asserts. The this asserts are removed the following line
+        // needs to be removed.
+        friend class nsHttpConnectionMgr;
+
+        RefPtr<nsConnectionEntry>      mEnt;
+        nsCOMPtr<nsITimer>             mSynTimer;
+        nsCOMPtr<nsISocketTransport>   mBackupTransport;
+        nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut;
+        nsCOMPtr<nsIAsyncInputStream>  mBackupStreamIn;
     };
     friend class nsHalfOpenSocket;
 
     class PendingTransactionInfo : public ARefBase
     {
     public:
         explicit PendingTransactionInfo(nsHttpTransaction * trans)
             : mTransaction(trans)
@@ -653,17 +665,17 @@ private:
 
     //
     // the connection table
     //
     // this table is indexed by connection key.  each entry is a
     // nsConnectionEntry object. It is unlocked and therefore must only
     // be accessed from the socket thread.
     //
-    nsClassHashtable<nsCStringHashKey, nsConnectionEntry> mCT;
+    nsRefPtrHashtable<nsCStringHashKey, nsConnectionEntry> mCT;
 
     // Read Timeout Tick handlers
     void TimeoutTick();
 
     // For diagnostics
     void OnMsgPrintDiagnostics(int32_t, ARefBase *);
 
     nsCString mLogData;