From 3674afe8a085613213fcb1e38dc203fa4f7161d5 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 4 Feb 2026 01:46:36 +0000 Subject: [PATCH] BUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING and clr FL_NOTIFIED When we're about to enter polling, atomically set TH_FL_SLEEPING and remove TH_FL_NOTIFIED, instead of doing it in sequence. Otherwise, another thread may sett that both the TH_FL_SLEEPING and the TH_FL_NOTIFIED bits are set, and don't wake up the thread then it should be doing that. This prevents a bug where a thread is sleeping while it should be handling a new connection, which can happen if there are very few incoming connection. This is easy to reproduce when using only two threads, and injecting with only one connection, the connection may then never be handled. This should be backported up to 2.8. --- src/haproxy.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/haproxy.c b/src/haproxy.c index c4a755f5e..1ad4c58f8 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2918,9 +2918,12 @@ void run_poll_loop() if (thread_has_tasks()) activity[tid].wake_tasks++; else { - _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING); - _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED); - __ha_barrier_atomic_store(); + unsigned int flags = _HA_ATOMIC_LOAD(&th_ctx->flags); + + while (unlikely(!HA_ATOMIC_CAS(&th_ctx->flags, &flags, +(flags | TH_FL_SLEEPING) & ~TH_FL_NOTIFIED))) + __ha_cpu_relax(); + if (thread_has_tasks()) { activity[tid].wake_tasks++; _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);