diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 746a0d120..880aa584d 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -222,11 +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. - * 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); + /* Now let's wait for polled events. */ + wait_time = wake ? 0 : compute_poll_timeout(exp); clock_entering_poll(); + do { int timeout = (global.tune.options & GTUNE_BUSY_POLLING) ? 0 : wait_time; @@ -239,7 +238,7 @@ static void _do_poll(struct poller *p, int exp, int wake) } if (timeout || !wait_time) break; - if (signal_queue_len || wake) + if (wake) break; if (tick_isset(exp) && tick_is_expired(exp, now_ms)) break; diff --git a/src/ev_evports.c b/src/ev_evports.c index 7d3e8a8d7..0a7df15d3 100644 --- a/src/ev_evports.c +++ b/src/ev_evports.c @@ -178,10 +178,8 @@ static void _do_poll(struct poller *p, int exp, int wake) thread_idle_now(); thread_harmless_now(); - /* 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); + /* Now let's wait for polled events. */ + wait_time = wake ? 0 : compute_poll_timeout(exp); clock_entering_poll(); do { @@ -219,7 +217,7 @@ static void _do_poll(struct poller *p, int exp, int wake) break; if (timeout || !wait_time) break; - if (signal_queue_len || wake) + if (wake) break; if (tick_isset(exp) && tick_is_expired(exp, now_ms)) break; diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 1d6e91d50..4796e680a 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -166,10 +166,8 @@ static void _do_poll(struct poller *p, int exp, int wake) } fd_nbupdt = 0; - /* 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); + /* Now let's wait for polled events. */ + wait_time = wake ? 0 : compute_poll_timeout(exp); fd = global.tune.maxpollevents; clock_entering_poll(); @@ -193,7 +191,7 @@ static void _do_poll(struct poller *p, int exp, int wake) } if (timeout || !wait_time) break; - if (signal_queue_len || wake) + if (wake) break; if (tick_isset(exp) && tick_is_expired(exp, now_ms)) break; diff --git a/src/ev_poll.c b/src/ev_poll.c index 6fefb3ab3..e98630c71 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -204,10 +204,8 @@ static void _do_poll(struct poller *p, int exp, int wake) } } - /* 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); + /* Now let's wait for polled events. */ + wait_time = wake ? 0 : compute_poll_timeout(exp); clock_entering_poll(); status = poll(poll_events, nbfd, wait_time); clock_update_date(wait_time, status); diff --git a/src/haproxy.c b/src/haproxy.c index 2eb84bd87..8d6f58766 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2810,7 +2810,7 @@ void run_poll_loop() if (killed > 1) break; - /* expire immediately if events are pending */ + /* expire immediately if events or signals are pending */ wake = 1; if (thread_has_tasks()) activity[tid].wake_tasks++; @@ -2821,6 +2821,10 @@ void run_poll_loop() if (thread_has_tasks()) { activity[tid].wake_tasks++; _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING); + } else if (signal_queue_len) { + /* this check is required after setting TH_FL_SLEEPING to avoid + * a race with wakeup on signals using wake_threads() */ + _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING); } else wake = 0; } diff --git a/src/signal.c b/src/signal.c index 5ec71429c..3d7a9a898 100644 --- a/src/signal.c +++ b/src/signal.c @@ -56,6 +56,9 @@ void signal_handler(int sig) signal_state[sig].count++; if (sig) signal(sig, signal_handler); /* re-arm signal */ + + /* If the thread is TH_FL_SLEEPING we need to wake it */ + wake_thread(tid); } /* Call handlers of all pending signals and clear counts and queue length. The