]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
OPTIM: poll: enable support for POLLRDHUP
authorWilly Tarreau <w@1wt.eu>
Mon, 13 Mar 2017 16:14:51 +0000 (17:14 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 21 Mar 2017 15:30:44 +0000 (16:30 +0100)
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

index 9a6faa9bf718a3d61ea358429f73880ea8ad9d5b..90ac9e5e1206a0ccabef7e50a0b4540ac148cca1 100644 (file)
  *
  */
 
+#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>
 
 #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];
 
 /* 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);