Bug 848946: In shutdown, don't wait for DataChannel closes to go to peer and back r=mcmanus
authorRandell Jesup <rjesup@jesup.org>
Mon, 25 Mar 2013 18:33:32 -0400
changeset 136582 b7a38caee2b5538e12dca8edac9c6244bcac5875
parent 136581 3a535bd50a23339d99808ac0e312f7ccdee2b48b
child 136583 67cb3a9a4ad1f7c6aa4907cbf4de364ce4664dce
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus
bugs848946
milestone22.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 848946: In shutdown, don't wait for DataChannel closes to go to peer and back r=mcmanus
netwerk/sctp/datachannel/DataChannel.cpp
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -1609,16 +1609,17 @@ DataChannelConnection::HandleStreamReset
           LOG(("Incoming: Channel %d outgoing/%d incoming closed, state %d",
                channel->mStreamOut, channel->mStreamIn, channel->mState));
           MOZ_ASSERT(channel->mState == DataChannel::OPEN ||
                      channel->mState == DataChannel::CLOSING ||
                      channel->mState == DataChannel::WAITING_TO_OPEN);
           if (channel->mState == DataChannel::OPEN ||
               channel->mState == DataChannel::WAITING_TO_OPEN) {
             ResetOutgoingStream(channel->mStreamOut);
+            SendOutgoingStreamReset();
             NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
                                       DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
                                       channel));
             mStreamsOut[channel->mStreamOut] = nullptr;
           }
           mStreamsIn[channel->mStreamIn] = nullptr;
 
           LOG(("Disconnected DataChannel %p from connection %p",
@@ -2117,43 +2118,66 @@ DataChannelConnection::Close(DataChannel
        channel->mConnection.get(), channel.get(), channel->mStreamOut));
   if (channel->mState == CLOSED || channel->mState == CLOSING) {
     LOG(("Channel already closing/closed (%d)", channel->mState));
     return;
   }
   channel->mBufferedData.Clear();
   if (channel->mStreamOut != INVALID_STREAM) {
     ResetOutgoingStream(channel->mStreamOut);
-    SendOutgoingStreamReset();
+    if (mState == CLOSED) { // called from CloseAll()
+      // Let resets accumulate then send all at once in CloseAll()
+      // we're not going to hang around waiting
+      mStreamsOut[channel->mStreamOut] = nullptr;
+    } else {
+      SendOutgoingStreamReset();
+    }
   }
   channel->mState = CLOSING;
+  if (mState == CLOSED) {
+    // we're not going to hang around waiting
+    if (channel->mStreamOut != INVALID_STREAM) {
+      mStreamsIn[channel->mStreamIn] = nullptr;
+    }
+    channel->Destroy();
+  }
+  // At this point when we leave here, the object is a zombie held alive only by the DOM object
 }
 
 void DataChannelConnection::CloseAll()
 {
   LOG(("Closing all channels"));
   // Don't need to lock here
 
   // Make sure no more channels will be opened
   mState = CLOSED;
 
   // Close current channels
   // If there are runnables, they hold a strong ref and keep the channel
   // and/or connection alive (even if in a CLOSED state)
+  bool closed_some = false;
   for (uint32_t i = 0; i < mStreamsOut.Length(); ++i) {
     if (mStreamsOut[i]) {
       mStreamsOut[i]->Close();
+      closed_some = true;
     }
   }
 
   // Clean up any pending opens for channels
   nsRefPtr<DataChannel> channel;
   while (nullptr != (channel = dont_AddRef(static_cast<DataChannel *>(mPending.PopFront())))) {
     LOG(("closing pending channel %p, stream %d", channel.get(), channel->mStreamOut));
     channel->Close(); // also releases the ref on each iteration
+    closed_some = true;
+  }
+  // It's more efficient to let the Resets queue in shutdown and then
+  // SendOutgoingStreamReset() here.
+  if (closed_some) {
+    MutexAutoLock lock(mLock);
+    SendOutgoingStreamReset();
   }
 }
 
 DataChannel::~DataChannel()
 {
   Close();
 }