bug 809984 HTTP Connections drain socket input before close to avoid TCP RST r=biesi
authorPatrick McManus <mcmanus@ducksong.com>
Thu, 08 Nov 2012 21:10:24 -0500
changeset 112768 f3fa8d88ab2d
parent 112767 bb8f67c67811
child 112769 0af82e65292b
push id23838
push usereakhgari@mozilla.com
push date2012-11-09 15:21 +0000
treeherdermozilla-central@c39596b46863 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbiesi
bugs809984
milestone19.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 809984 HTTP Connections drain socket input before close to avoid TCP RST r=biesi
netwerk/protocol/http/nsHttpConnection.cpp
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -478,18 +478,37 @@ nsHttpConnection::Close(nsresult reason)
 
     NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     if (NS_FAILED(reason)) {
         if (mIdleMonitoring)
             EndIdleMonitoring();
 
         if (mSocketTransport) {
+            mSocketTransport->SetEventSink(nullptr, nullptr);
+
+            // If there are bytes sitting in the input queue then read them
+            // into a junk buffer to avoid generating a tcp rst by closing a
+            // socket with data pending. TLS is a classic case of this where
+            // a Alert record might be superfulous to a clean HTTP/SPDY shutdown.
+            // Never block to do this and limit it to a small amount of data.
+            if (mSocketIn) {
+                char buffer[4000];
+                uint32_t count, total = 0;
+                nsresult rv;
+                do {
+                    rv = mSocketIn->Read(buffer, 4000, &count);
+                    if (NS_SUCCEEDED(rv))
+                        total += count;
+                }
+                while (NS_SUCCEEDED(rv) && count > 0 && total < 64000);
+                LOG(("nsHttpConnection::Close drained %d bytes\n", total));
+            }
+            
             mSocketTransport->SetSecurityCallbacks(nullptr);
-            mSocketTransport->SetEventSink(nullptr, nullptr);
             mSocketTransport->Close(reason);
             if (mSocketOut)
                 mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
         }
         mKeepAlive = false;
     }
 }