From: Willy Tarreau Date: Fri, 13 Jun 2008 19:06:56 +0000 (+0200) Subject: [BUG] event pollers must not wait if a task exists in the run queue X-Git-Tag: v1.3.16-rc1~261 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a6281199ab261568d2dce8714996c89d741292d;p=thirdparty%2Fhaproxy.git [BUG] event pollers must not wait if a task exists in the run queue Under some circumstances, a task may already lie in the run queue (eg: inter-task wakeup). It is disastrous to wait for an event in this case because some processing gets delayed. --- diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 326d5a42ed..0ce68b05ec 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -232,7 +232,9 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) fd_flush_changes(); /* now let's wait for events */ - if (tv_iseternity(exp)) + if (run_queue) + wait_time = 0; + else if (tv_iseternity(exp)) wait_time = -1; else if (tv_isge(&now, exp)) wait_time = 0; diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 773db74a3b..f34cdc3c1b 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -106,7 +106,11 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) struct timespec timeout, *to_ptr; to_ptr = NULL; // no timeout - if (tv_isset(exp)) { + if (run_queue) { + timeout.tv_sec = timeout.tv_nsec = 0; + to_ptr = &timeout; + } + else if (tv_isset(exp)) { struct timeval delta; if (tv_isge(&now, exp)) diff --git a/src/ev_poll.c b/src/ev_poll.c index 54cd1389a9..63dce5b26c 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -124,7 +124,9 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) } /* now let's wait for events */ - if (tv_iseternity(exp)) + if (run_queue) + wait_time = 0; + else if (tv_iseternity(exp)) wait_time = -1; else if (tv_isge(&now, exp)) wait_time = 0; diff --git a/src/ev_select.c b/src/ev_select.c index 1b897de2e4..bbbbfe0ccc 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -89,7 +89,7 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) /* allow select to return immediately when needed */ delta.tv_sec = delta.tv_usec = 0; - if (tv_isset(exp)) { + if (!run_queue && tv_isset(exp)) { if (tv_islt(&now, exp)) { tv_remain(&now, exp, &delta); /* To avoid eventual select loops due to timer precision */ diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c index 26c5b03ccb..800ac0bab2 100644 --- a/src/ev_sepoll.c +++ b/src/ev_sepoll.c @@ -424,9 +424,10 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) } last_skipped = 0; - if (nbspec || status) { + if (nbspec || status || run_queue) { /* Maybe we have processed some events that we must report, or - * maybe we still have events in the spec list, so we must not + * maybe we still have events in the spec list, or there are + * some tasks left pending in the run_queue, so we must not * wait in epoll() otherwise we will delay their delivery by * the next timeout. */