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.
diff --git a/src/ev_poll.c b/src/ev_poll.c
index 9a6faa9..90ac9e5 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -10,8 +10,10 @@
*
*/
+#define _GNU_SOURCE // for POLLRDHUP on Linux
+
#include <unistd.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -24,6 +26,11 @@
#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];
@@ -102,7 +109,7 @@
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 @@
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 @@
((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);