OPTIM: poll: enable support for POLLRDHUP

On Linux since 2.6.17 poll() supports POLLRDHUP to notify of an upcoming
hangup after pending data. Making use of it allows us to avoid a useless
recv() after short responses on keep-alive connections. Note that we
automatically enable the feature once this flag has been met first in a
poll() status. Till now it was only enabled on epoll.
This commit is contained in:
Willy Tarreau 2017-03-13 17:14:51 +01:00
parent 68128710d0
commit 3c8a89642d

View File

@ -10,8 +10,10 @@
* *
*/ */
#define _GNU_SOURCE // for POLLRDHUP on Linux
#include <unistd.h> #include <unistd.h>
#include <sys/poll.h> #include <poll.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
@ -25,6 +27,11 @@
#include <proto/fd.h> #include <proto/fd.h>
#ifndef POLLRDHUP
/* POLLRDHUP was defined late in libc, and it appeared in kernel 2.6.17 */
#define POLLRDHUP 0
#endif
static unsigned int *fd_evts[2]; static unsigned int *fd_evts[2];
/* private data */ /* private data */
@ -102,7 +109,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
sw = (wn >> count) & 1; sw = (wn >> count) & 1;
if ((sr|sw)) { if ((sr|sw)) {
poll_events[nbfd].fd = fd; poll_events[nbfd].fd = fd;
poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0); poll_events[nbfd].events = (sr ? (POLLIN | POLLRDHUP) : 0) | (sw ? POLLOUT : 0);
nbfd++; nbfd++;
} }
} }
@ -128,7 +135,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
int e = poll_events[count].revents; int e = poll_events[count].revents;
fd = poll_events[count].fd; fd = poll_events[count].fd;
if (!(e & ( POLLOUT | POLLIN | POLLERR | POLLHUP ))) if (!(e & ( POLLOUT | POLLIN | POLLERR | POLLHUP | POLLRDHUP )))
continue; continue;
/* ok, we found one active fd */ /* ok, we found one active fd */
@ -153,6 +160,12 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
((e & POLLHUP) ? FD_POLL_HUP : 0); ((e & POLLHUP) ? FD_POLL_HUP : 0);
} }
/* always remap RDHUP to HUP as they're used similarly */
if (e & POLLRDHUP) {
cur_poller.flags |= HAP_POLL_F_RDHUP;
fdtab[fd].ev |= FD_POLL_HUP;
}
if (fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR)) if (fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR))
fd_may_recv(fd); fd_may_recv(fd);