From: Ming Fu Date: Tue, 21 May 2013 05:17:23 +0000 (-0600) Subject: Bug 1991: kqueue causes SSL to hang X-Git-Tag: SQUID_3_4_0_1~120 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5f84968c5834fa28bf9c5485e34948ae3e09b952;p=thirdparty%2Fsquid.git Bug 1991: kqueue causes SSL to hang 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. --- diff --git a/src/comm/ModKqueue.cc b/src/comm/ModKqueue.cc index 8b722246db..40b51a2e52 100644 --- a/src/comm/ModKqueue.cc +++ b/src/comm/ModKqueue.cc @@ -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; } }