]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: polling: some events were not set in various pollers
authorWilly Tarreau <w@1wt.eu>
Fri, 6 Jul 2012 09:16:01 +0000 (11:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Jul 2012 05:55:31 +0000 (07:55 +0200)
fdtab[].ev was only set in ev_sepoll. Unfortunately, some I/O handling
functions now rely on this, so depending on the polling mechanism, some
useless operations might have been performed, such as performing a useless
recv() when a HUP was reported.

This is a very old issue, the flags were only added to the fdtab and not
propagated into any poller. Then they were used in ev_sepoll which needed
them for the cache. It is unsure whether a backport to 1.4 is appropriate
or not.

src/ev_epoll.c
src/ev_kqueue.c
src/ev_poll.c
src/ev_select.c
src/ev_sepoll.c

index bc7493b406a0372a2413817bb4d8fa2713a126b4..7026d56d300a7c42a771127dd9fe05606ae1f904 100644 (file)
@@ -242,19 +242,31 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
        measure_idle();
 
        for (count = 0; count < status; count++) {
+               int e = epoll_events[count].events;
                fd = epoll_events[count].data.fd;
 
+               /* it looks complicated but gcc can optimize it away when constants
+                * have same values.
+                */
+               fdtab[fd].ev &= FD_POLL_STICKY;
+               fdtab[fd].ev |=
+                       ((e & EPOLLIN ) ? FD_POLL_IN  : 0) |
+                       ((e & EPOLLPRI) ? FD_POLL_PRI : 0) |
+                       ((e & EPOLLOUT) ? FD_POLL_OUT : 0) |
+                       ((e & EPOLLERR) ? FD_POLL_ERR : 0) |
+                       ((e & EPOLLHUP) ? FD_POLL_HUP : 0);
+
                if ((fd_evts[FD2OFS(fd)] >> FD2BIT(fd)) & DIR2MSK(DIR_RD)) {
                        if (fdtab[fd].state == FD_STCLOSE)
                                continue;
-                       if (epoll_events[count].events & ( EPOLLIN | EPOLLERR | EPOLLHUP ))
+                       if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
                                fdtab[fd].cb[DIR_RD].f(fd);
                }
 
                if ((fd_evts[FD2OFS(fd)] >> FD2BIT(fd)) & DIR2MSK(DIR_WR)) {
                        if (fdtab[fd].state == FD_STCLOSE)
                                continue;
-                       if (epoll_events[count].events & ( EPOLLOUT | EPOLLERR | EPOLLHUP ))
+                       if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR|FD_POLL_HUP))
                                fdtab[fd].cb[DIR_WR].f(fd);
                }
        }
index b43533ab5c09bdcd5081589477ae779c2090805b..df4f920b754d93fb36233d3e5a04e3d6fbeda033 100644 (file)
@@ -142,12 +142,14 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                        if (FD_ISSET(fd, fd_evts[DIR_RD])) {
                                if (fdtab[fd].state == FD_STCLOSE)
                                        continue;
+                               fdtab[fd].ev |= FD_POLL_IN;
                                fdtab[fd].cb[DIR_RD].f(fd);
                        }
                } else if (kev[count].filter ==  EVFILT_WRITE) {
                        if (FD_ISSET(fd, fd_evts[DIR_WR])) {
                                if (fdtab[fd].state == FD_STCLOSE)
                                        continue;
+                               fdtab[fd].ev |= FD_POLL_OUT;
                                fdtab[fd].cb[DIR_WR].f(fd);
                        }
                }
index ec18863b44f9bc2b285f782c0caa089c9fb07f06..8f2e1d986edd6bd4708c306f4a1f0a7459a53ee6 100644 (file)
@@ -143,25 +143,33 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
        measure_idle();
 
        for (count = 0; status > 0 && count < nbfd; count++) {
+               int e = poll_events[count].revents;
                fd = poll_events[count].fd;
          
-               if (!(poll_events[count].revents & ( POLLOUT | POLLIN | POLLERR | POLLHUP )))
+               if (!(e & ( POLLOUT | POLLIN | POLLERR | POLLHUP )))
                        continue;
 
+               fdtab[fd].ev &= FD_POLL_STICKY;
+               fdtab[fd].ev |=
+                       ((e & POLLIN ) ? FD_POLL_IN  : 0) |
+                       ((e & POLLOUT) ? FD_POLL_OUT : 0) |
+                       ((e & POLLERR) ? FD_POLL_ERR : 0) |
+                       ((e & POLLHUP) ? FD_POLL_HUP : 0);
+
                /* ok, we found one active fd */
                status--;
 
                if (FD_ISSET(fd, fd_evts[DIR_RD])) {
                        if (fdtab[fd].state == FD_STCLOSE)
                                continue;
-                       if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP ))
+                       if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
                                fdtab[fd].cb[DIR_RD].f(fd);
                }
          
                if (FD_ISSET(fd, fd_evts[DIR_WR])) {
                        if (fdtab[fd].state == FD_STCLOSE)
                                continue;
-                       if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP ))
+                       if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR|FD_POLL_HUP))
                                fdtab[fd].cb[DIR_WR].f(fd);
                }
        }
index 0924e3fda99a0fddaddb4ba93b6d4d274bd25eb9..72eca0b3f42e85a61e2df35bd87aa112bc55b581 100644 (file)
@@ -149,12 +149,14 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                        if (FD_ISSET(fd, tmp_evts[DIR_RD])) {
                                if (fdtab[fd].state == FD_STCLOSE)
                                        continue;
+                               fdtab[fd].ev |= FD_POLL_IN;
                                fdtab[fd].cb[DIR_RD].f(fd);
                        }
 
                        if (FD_ISSET(fd, tmp_evts[DIR_WR])) {
                                if (fdtab[fd].state == FD_STCLOSE)
                                        continue;
+                               fdtab[fd].ev |= FD_POLL_OUT;
                                fdtab[fd].cb[DIR_WR].f(fd);
                        }
                }
index c8444bee3c4ce2477ac3bdb3bc43db97b76a505c..b5048157bd8dc62ca31937dee44d95fc7b20f838 100644 (file)
@@ -402,13 +402,13 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                 * have same values.
                 */
                fdtab[fd].ev &= FD_POLL_STICKY;
-               fdtab[fd].ev |= 
+               fdtab[fd].ev |=
                        ((e & EPOLLIN ) ? FD_POLL_IN  : 0) |
                        ((e & EPOLLPRI) ? FD_POLL_PRI : 0) |
                        ((e & EPOLLOUT) ? FD_POLL_OUT : 0) |
                        ((e & EPOLLERR) ? FD_POLL_ERR : 0) |
                        ((e & EPOLLHUP) ? FD_POLL_HUP : 0);
-               
+
                if ((fdtab[fd].spec.e & FD_EV_MASK_R) == FD_EV_WAIT_R) {
                        if (fdtab[fd].state == FD_STCLOSE || fdtab[fd].state == FD_STERROR)
                                continue;