]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fix regression in client read buffer
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 6 Jun 2014 09:38:02 +0000 (02:38 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 6 Jun 2014 09:38:02 +0000 (02:38 -0700)
SBuf acts like a floating 'window' of space in a MemBlob which acts a
essentially like a ring-buffer. However on requests with body payload
being drop-fed in very small amounts it is possible to exactly fill the
MemBlob and also to shuffle the SBuf window right to the end.
It is also possible if an earlier request (or the headers associated with
the drip-fed body is holding the beginning of the underlying MemBlob.
 These events cause haveCapadity==0 so haveCapacity*2 == 0.

If this happens we need to allocate a new MemBlob to get any space for
future I/O. The old MemBlob will be released by whatever other SBuf was
holding it locked.

src/client_side.cc

index 9c8890849b740f62cac2c153b49e83ae10253240..56a00c141149de897569c1f9485b6b1b56ff7596 100644 (file)
@@ -2387,9 +2387,15 @@ ConnStateData::In::maybeMakeSpaceAvailable()
             debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize);
             return false;
         }
-        const SBuf::size_type wantCapacity = min(static_cast<SBuf::size_type>(Config.maxRequestBufferSize), haveCapacity*2);
-        buf.reserveCapacity(wantCapacity);
-        debugs(33, 2, "growing request buffer: available=" << buf.spaceSize() << " used=" << buf.length());
+        if (haveCapacity == 0) {
+            // haveCapacity is based on the SBuf visible window of the MemBlob buffer, which may fill up.
+            // at which point bump the buffer back to default. This allocates a new MemBlob with any un-parsed bytes.
+            buf.reserveCapacity(CLIENT_REQ_BUF_SZ);
+        } else {
+            const SBuf::size_type wantCapacity = min(static_cast<SBuf::size_type>(Config.maxRequestBufferSize), haveCapacity*2);
+            buf.reserveCapacity(wantCapacity);
+        }
+        debugs(33, 2, "growing request buffer: available=" << buf.spaceSize() << " used=" << buf.length() << " want=" << wantCapacity);
     }
     return (buf.spaceSize() >= 2);
 }
@@ -3276,7 +3282,8 @@ ConnStateData::ConnStateData(const MasterXaction::Pointer &xact) :
     log_addr = xact->tcpClient->remote;
     log_addr.applyMask(Config.Addrs.client_netmask);
 
-    in.buf.reserveCapacity(CLIENT_REQ_BUF_SZ);
+    // ensure a buffer is present for this connection
+    in.maybeMakeSpaceAvailable();
 
     if (port->disable_pmtu_discovery != DISABLE_PMTU_OFF &&
             (transparent() || port->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)) {