From: William Lallemand Date: Thu, 8 Sep 2022 15:46:31 +0000 (+0200) Subject: BUG/MINOR: signals/poller: set the poller timeout to 0 when there are signals X-Git-Tag: v2.7-dev6~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43c891dda;p=thirdparty%2Fhaproxy.git BUG/MINOR: signals/poller: set the poller timeout to 0 when there are signals When receiving a signal before entering the poller, and without any activity in the process, the poller will be entered with a timeout calculated without checking the signals. Since commit 4f59d3 ("MINOR: time: increase the minimum wakeup interval to 60s") the issue is much more visible because it could be stuck for 60s. When in mworker mode, if a worker quits and the SIGCHLD signal deliver at the right time to the master, this one could be stuck for the time of the timeout. This should fix issue #1841 Must be backported in every stable version. --- diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 98ca701e19..746a0d120a 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -222,8 +222,10 @@ static void _do_poll(struct poller *p, int exp, int wake) thread_idle_now(); thread_harmless_now(); - /* now let's wait for polled events */ - wait_time = wake ? 0 : compute_poll_timeout(exp); + /* Now let's wait for polled events. + * Check if the signal queue is not empty in case we received a signal + * before entering the loop, so we don't wait MAX_DELAY_MS for nothing */ + wait_time = (wake | signal_queue_len) ? 0 : compute_poll_timeout(exp); clock_entering_poll(); do { int timeout = (global.tune.options & GTUNE_BUSY_POLLING) ? 0 : wait_time; diff --git a/src/ev_evports.c b/src/ev_evports.c index 2530b39c04..7d3e8a8d77 100644 --- a/src/ev_evports.c +++ b/src/ev_evports.c @@ -178,10 +178,10 @@ static void _do_poll(struct poller *p, int exp, int wake) thread_idle_now(); thread_harmless_now(); - /* - * Determine how long to wait for events to materialise on the port. - */ - wait_time = wake ? 0 : compute_poll_timeout(exp); + /* Now let's wait for polled events. + * Check if the signal queue is not empty in case we received a signal + * before entering the loop, so we don't wait MAX_DELAY_MS for nothing */ + wait_time = (wake | signal_queue_len) ? 0 : compute_poll_timeout(exp); clock_entering_poll(); do { diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 3c8787ffd7..1d6e91d506 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -166,8 +166,10 @@ static void _do_poll(struct poller *p, int exp, int wake) } fd_nbupdt = 0; - /* now let's wait for events */ - wait_time = wake ? 0 : compute_poll_timeout(exp); + /* Now let's wait for polled events. + * Check if the signal queue is not empty in case we received a signal + * before entering the loop, so we don't wait MAX_DELAY_MS for nothing */ + wait_time = (wake | signal_queue_len) ? 0 : compute_poll_timeout(exp); fd = global.tune.maxpollevents; clock_entering_poll(); diff --git a/src/ev_poll.c b/src/ev_poll.c index 790ea5bfaf..6fefb3ab3f 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -203,8 +204,10 @@ static void _do_poll(struct poller *p, int exp, int wake) } } - /* now let's wait for events */ - wait_time = wake ? 0 : compute_poll_timeout(exp); + /* Now let's wait for polled events. + * Check if the signal queue is not empty in case we received a signal + * before entering the loop, so we don't wait MAX_DELAY_MS for nothing */ + wait_time = (wake | signal_queue_len) ? 0 : compute_poll_timeout(exp); clock_entering_poll(); status = poll(poll_events, nbfd, wait_time); clock_update_date(wait_time, status);