From: Willy Tarreau Date: Thu, 6 Dec 2012 23:09:43 +0000 (+0100) Subject: BUG/MAJOR: polling: do not set speculative events on ERR nor HUP X-Git-Tag: v1.5-dev15~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=26d7cfce328c33e208437b30b4ca3fc2db359cd2;p=thirdparty%2Fhaproxy.git BUG/MAJOR: polling: do not set speculative events on ERR nor HUP Errors and Hangups are sticky events, which means that once they're detected, we never clear them, allowing them to be handled later if needed. Till now when an error was reported, it used to register a speculative I/O event for both recv and send. Since the connection had not requested such events, it was not able to detect a change and did not clear them, so the events were called in loops until a timeout caused their owner task to die. So this patch does two things : - stop registering spec events when no I/O activity was requested, so that we don't end up with non-disablable polling state ; - keep the sticky polling flags (ERR and HUP) when leaving the connection handler so that an error notification doesn't magically become a normal recv() or send() report once the event is converted to a spec event. It is normally not needed to make the connection handler emit an error when it detects POLL_ERR because either a registered data handler will have done it, or the event will be disabled by the wake() callback. --- diff --git a/src/connection.c b/src/connection.c index e2d75ba7a5..03a9bb08b4 100644 --- a/src/connection.c +++ b/src/connection.c @@ -153,7 +153,7 @@ int conn_fd_handler(int fd) conn->flags |= CO_FL_CONNECTED; /* remove the events before leaving */ - fdtab[fd].ev &= ~(FD_POLL_IN | FD_POLL_OUT | FD_POLL_HUP | FD_POLL_ERR); + fdtab[fd].ev &= FD_POLL_STICKY; /* commit polling changes */ conn_cond_update_polling(conn); diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 870da105de..2cd596aa39 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -161,10 +161,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) * them so that if nothing can be done we don't need * to poll again. */ - if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_IN) fd_ev_set(fd, DIR_RD); - if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_OUT) fd_ev_set(fd, DIR_WR); fdtab[fd].iocb(fd); diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 54c52c2ec1..36a7b7f41f 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -152,10 +152,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) * them so that if nothing can be done we don't need * to poll again. */ - if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_IN) fd_ev_set(fd, DIR_RD); - if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_OUT) fd_ev_set(fd, DIR_WR); fdtab[fd].iocb(fd); diff --git a/src/ev_poll.c b/src/ev_poll.c index 2ce4815d6e..cdc357fbea 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -166,10 +166,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) * them so that if nothing can be done we don't need * to poll again. */ - if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_IN) fd_ev_set(fd, DIR_RD); - if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_OUT) fd_ev_set(fd, DIR_WR); fdtab[fd].iocb(fd); diff --git a/src/ev_select.c b/src/ev_select.c index 0ac74e71d1..356eed735f 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -161,10 +161,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) * them so that if nothing can be done we don't need * to poll again. */ - if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_IN) fd_ev_set(fd, DIR_RD); - if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR)) + if (fdtab[fd].ev & FD_POLL_OUT) fd_ev_set(fd, DIR_WR); fdtab[fd].iocb(fd);