]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Make removeFD report failures and prevent non-idle FD being closed
authorAmos Jeffries <squid3@treenet.co.nz>
Thu, 16 Sep 2010 10:09:19 +0000 (22:09 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Thu, 16 Sep 2010 10:09:19 +0000 (22:09 +1200)
src/pconn.cc
src/pconn.h

index 414b9c1d4eab8f35cf90d80ad50cda9fa3ab97ac..a34b372786eb7eb222e49a8d1704fcb019005ec1 100644 (file)
@@ -81,13 +81,13 @@ IdleConnList::findFDIndex (int fd)
     return -1;
 }
 
-void
+bool
 IdleConnList::removeFD(int fd)
 {
     int index = findFDIndex(fd);
     if (index < 0) {
         debugs(48, 2, "IdleConnList::removeFD: FD " << fd << " NOT FOUND!");
-        return;
+        return false;
     }
     debugs(48, 3, "IdleConnList::removeFD: found FD " << fd << " at index " << index);
 
@@ -98,6 +98,7 @@ IdleConnList::removeFD(int fd)
         debugs(48, 3, "IdleConnList::removeFD: deleting " << hashKeyStr(&hash));
         delete this;
     }
+    return true;
 }
 
 void
@@ -161,8 +162,8 @@ IdleConnList::read(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, v
     }
 
     IdleConnList *list = (IdleConnList *) data;
-    list->removeFD(fd);        /* might delete list */
-    comm_close(fd);
+    if (list->removeFD(fd))    /* might delete list */
+        comm_close(fd);
 }
 
 void
@@ -170,8 +171,8 @@ IdleConnList::timeout(int fd, void *data)
 {
     debugs(48, 3, "IdleConnList::timeout: FD " << fd);
     IdleConnList *list = (IdleConnList *) data;
-    list->removeFD(fd);        /* might delete list */
-    comm_close(fd);
+    if (list->removeFD(fd))    /* might delete list */
+        comm_close(fd);
 }
 
 /* ========== PconnPool PRIVATE FUNCTIONS ============================================ */
@@ -309,9 +310,9 @@ PconnPool::pop(const char *host, u_short port, const char *domain, Ip::Address &
 
     if (fd >= 0) {
         list->clearHandlers(fd);
-        list->removeFD(fd);    /* might delete list */
 
-        if (!isRetriable) {
+        /* might delete list */
+        if (list->removeFD(fd) && !isRetriable) {
             comm_close(fd);
             return -1;
         }
index 5566fc9d2916c275701249233f683381cc568450..f52f3f5b5b2eeba4f88088334f14eb5751a7dec9 100644 (file)
@@ -38,7 +38,12 @@ public:
     int numIdle() { return nfds; }
 
     int findFDIndex(int fd); ///< search from the end of array
-    void removeFD(int fd);
+
+    /// If false the FD does not currently exist in the list.
+    /// We seem to have hit and lost a race condition.
+    /// Nevermind, but MUST NOT do anything with the raw FD.
+    bool removeFD(int fd);
+
     void push(int fd);
     int findUseableFD();     ///< find first from the end not pending read fd.
     void clearHandlers(int fd);