From 3c8a89642d6d8b3f098daaff24edcb5aa23e58a0 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 13 Mar 2017 17:14:51 +0100 Subject: [PATCH] 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. --- src/ev_poll.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/ev_poll.c b/src/ev_poll.c index 9a6faa9bf..90ac9e5e1 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -10,8 +10,10 @@ * */ +#define _GNU_SOURCE // for POLLRDHUP on Linux + #include -#include +#include #include #include @@ -25,6 +27,11 @@ #include +#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]; /* private data */ @@ -102,7 +109,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) sw = (wn >> count) & 1; if ((sr|sw)) { 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++; } } @@ -128,7 +135,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) int e = poll_events[count].revents; fd = poll_events[count].fd; - if (!(e & ( POLLOUT | POLLIN | POLLERR | POLLHUP ))) + if (!(e & ( POLLOUT | POLLIN | POLLERR | POLLHUP | POLLRDHUP ))) continue; /* 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); } + /* 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)) fd_may_recv(fd);