]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Alex Rousskov <rousskov@measurement-factory.com>
authorAmos Jeffries <amosjeffries@squid-cache.org>
Fri, 23 Jul 2010 04:30:08 +0000 (22:30 -0600)
committerAmos Jeffries <amosjeffries@squid-cache.org>
Fri, 23 Jul 2010 04:30:08 +0000 (22:30 -0600)
Fixed comm.cc:377: "fd_table[fd].halfClosedReader != NULL" assertion

Client side must stop reading when switching to a tunnel mode. The old code
called low-level commSetSelect to stop reading, but that left Comm tables in
an inconsistent state, with the client side reader callback still scheduled.
Squid would assert when the tunnel called comm_read with its own callback.

The bug is unrelated to half-closed connections despite halfClosedReader
mentioned in the assertion text. The assertion means "no more than one active
reader per FD".

src/client_side.cc
src/client_side.h
src/client_side_request.cc
src/tunnel.cc

index fcf16e86d94114fa716d1c54af0320f78555f97d..a3f4b8d90d79b51abf374b7c7e61e32d766631c1 100644 (file)
@@ -205,16 +205,14 @@ ConnStateData::readSomeData()
     if (reading())
         return;
 
-    reading(true);
-
     debugs(33, 4, "clientReadSomeData: FD " << fd << ": reading request...");
 
     makeSpaceAvailable();
 
     typedef CommCbMemFunT<ConnStateData, CommIoCbParams> Dialer;
-    AsyncCall::Pointer call = asyncCall(33, 5, "ConnStateData::clientReadRequest",
-                                        Dialer(this, &ConnStateData::clientReadRequest));
-    comm_read(fd, in.addressToReadInto(), getAvailableBufferLength(), call);
+    reader = asyncCall(33, 5, "ConnStateData::clientReadRequest",
+                       Dialer(this, &ConnStateData::clientReadRequest));
+    comm_read(fd, in.addressToReadInto(), getAvailableBufferLength(), reader);
 }
 
 
@@ -2669,7 +2667,8 @@ void
 ConnStateData::clientReadRequest(const CommIoCbParams &io)
 {
     debugs(33,5,HERE << "clientReadRequest FD " << io.fd << " size " << io.size);
-    reading(false);
+    Must(reading());
+    reader = NULL;
     bool do_next_read = 1; /* the default _is_ to read data! - adrian */
 
     assert (io.fd == fd);
@@ -3563,7 +3562,7 @@ clientAclChecklistCreate(const acl_access * acl, ClientHttpRequest * http)
 
 CBDATA_CLASS_INIT(ConnStateData);
 
-ConnStateData::ConnStateData() :AsyncJob("ConnStateData"), transparent_ (false), reading_ (false), closing_ (false)
+ConnStateData::ConnStateData() :AsyncJob("ConnStateData"), transparent_ (false), closing_ (false)
 {
     pinning.fd = -1;
     pinning.pinned = false;
@@ -3585,14 +3584,16 @@ ConnStateData::transparent(bool const anInt)
 bool
 ConnStateData::reading() const
 {
-    return reading_;
+    return reader != NULL;
 }
 
 void
-ConnStateData::reading(bool const newBool)
+ConnStateData::stopReading()
 {
-    assert (reading() != newBool);
-    reading_ = newBool;
+    if (reading()) {
+        comm_read_cancel(fd, reader);
+        reader = NULL;
+    }
 }
 
 
index 2c8ef911b7404649e515a134339f2c8ba1c472ef..5824b63966a54ab1affe4e98db260e04e450a719 100644 (file)
@@ -212,7 +212,7 @@ public:
     bool transparent() const;
     void transparent(bool const);
     bool reading() const;
-    void reading(bool const);
+    void stopReading(); ///< cancels comm_read if it is scheduled
 
     bool closing() const;
     void startClosing(const char *reason);
@@ -278,10 +278,10 @@ private:
 private:
     CBDATA_CLASS2(ConnStateData);
     bool transparent_;
-    bool reading_;
     bool closing_;
 
     bool switchedToHttps_;
+    AsyncCall::Pointer reader; ///< set when we are reading
     BodyPipe::Pointer bodyPipe; // set when we are reading request body
 };
 
index 6e8d3a6e89c67bfcb0f437bc96420fafbfb35846..b6ca7b7ce9dbe15dcd7198c7a8a92cc8857dfd23 100644 (file)
@@ -1114,6 +1114,7 @@ ClientHttpRequest::processRequest()
 
     if (request->method == METHOD_CONNECT && !redirect.status) {
         logType = LOG_TCP_MISS;
+        getConn()->stopReading(); // tunnels read for themselves
         tunnelStart(this, &out.size, &al.http.code);
         return;
     }
index ba33df3c9535f576829855c6b43f1f39e6b00615..8948c5dc39667315f7c6ddba73a58c2d422a9fd1 100644 (file)
@@ -691,11 +691,6 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr)
                NULL,
                tunnelPeerSelectComplete,
                tunnelState);
-    /*
-     * Disable the client read handler until peer selection is complete
-     * Take control away from client_side.c.
-     */
-    commSetSelect(tunnelState->client.fd(), COMM_SELECT_READ, NULL, NULL, 0);
 }
 
 static void