From: Olivier Houchard Date: Fri, 14 Aug 2026 14:33:10 +0000 (+0200) Subject: BUG/MEDIUM: tasks: don't type-pun state and tid in builds without threads X-Git-Tag: v3.5-dev5~33 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=c5f41118c01db4babcf6919f5eae4ce308adcfef;p=haproxy.git BUG/MEDIUM: tasks: don't type-pun state and tid in builds without threads __task_set_state_and_tid() updates t->state and t->tid at once through an uint64_t cast, which violates strict aliasing. With threads the __atomic builtins keep the compiler conservative, but without them the accesses are plain, and gcc -O2 legitimately keeps using a stale t->state: the CAS always fails and _task_wakeup() spins forever on the first request until the watchdog kills the process. Without threads there is no concurrency to protect against, so just compare and assign the two fields directly. --- diff --git a/src/haproxy.c b/src/haproxy.c index 801bc6dfe..373429007 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -3946,18 +3946,6 @@ int main(int argc, char **argv) } } - /* When FD tables are not shared between thread groups, the poller - * pipes of all threads must be created before any group unshares its - * FD table, so that they are inherited into every group's table and - * cross-group wake_thread() keeps working. This must be done for all - * builds, including those without threads, since each thread will pick - * its own pair from there. - */ - if (!fd_precreate_poller_pipes()) { - ha_alert("Failed to create the poller pipes.\n"); - exit(1); - } - /* start threads 2 and above */ setup_extra_threads(&run_thread_poll_loop); diff --git a/src/thread.c b/src/thread.c index 3a6efe482..557af60fb 100644 --- a/src/thread.c +++ b/src/thread.c @@ -278,6 +278,16 @@ void setup_extra_threads(void *(*handler)(void *)) /* the startup thread will be thread 1 */ ha_pthread[0] = pthread_self(); + /* When FD tables are not shared between thread groups, the poller + * pipes of all threads must be created before any group unshares its + * FD table, so that they are inherited into every group's table and + * cross-group wake_thread() keeps working. + */ + if (!fd_precreate_poller_pipes()) { + ha_alert("Failed to create the poller pipes.\n"); + exit(1); + } + /* Create one initial thread for each extra thread group. These will * each be responsible for creating their own extra threads. The first * group's initial thread is the current thread.