]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 1991: kqueue causes SSL to hang
authorMing Fu <mfu@watchguard.com>
Tue, 21 May 2013 05:17:23 +0000 (23:17 -0600)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 21 May 2013 05:17:23 +0000 (23:17 -0600)
Compare the code in normal select and epoll v.s. kqueue. The select use a 0
wait time to get out of select wait in order to handle a list of read_pendings.
However, epoll add the read_pending to read and write event monitor. At a first
look, this seems strange as why read pending has anything to do with write. It
became obvious when the write ready event is triggered. During a write ready
event, if read_pending is on, the read callback is called before the write
callback. As the write buffer is unlikely to be full for an extended period, a
write callback is guaranteed in the immediate future for the read_pending
socket by waiting on write.

The patch follows that same logic as epoll and applies it on kqueue.

src/comm/ModKqueue.cc

index 8b722246dbcd8a5ba6618636d99a13185efbf0e4..40b51a2e52acbd99a7314d22a40f31f5cf1d7a48 100644 (file)
@@ -197,7 +197,11 @@ Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time
            ", timeout=" << timeout);
 
     if (type & COMM_SELECT_READ) {
+        if (F->flags.read_pending)
+            kq_update_events(fd, EVFILT_WRITE, handler);
         kq_update_events(fd, EVFILT_READ, handler);
+        
         F->read_handler = handler;
         F->read_data = client_data;
     }
@@ -290,31 +294,24 @@ Comm::DoSelect(int msec)
             continue;        /* XXX! */
         }
 
-        switch (ke[i].filter) {
-
-        case EVFILT_READ:
-
+        if (ke[i].filter == EVFILT_READ || F->flags.read_pending) {
             if ((hdl = F->read_handler) != NULL) {
                 F->read_handler = NULL;
                 F->flags.read_pending = 0;
                 hdl(fd, F->read_data);
             }
+        }
 
-            break;
-
-        case EVFILT_WRITE:
-
+        if (ke[i].filter == EVFILT_WRITE) {
             if ((hdl = F->write_handler) != NULL) {
                 F->write_handler = NULL;
                 hdl(fd, F->write_data);
             }
+        }
 
-            break;
-
-        default:
+        if (ke[i].filter != EVFILT_WRITE && ke[i].filter != EVFILT_READ) {
             /* Bad! -- adrian */
             debugs(5, DBG_IMPORTANT, "comm_select: kevent returned " << ke[i].filter << "!");
-            break;
         }
     }