From: Martin Mirchev Date: Tue, 27 Oct 2026 03:36:58 +0000 (+0800) Subject: BUG/MINOR: thread: don't turn reversed thread ranges into "even" X-Git-Tag: v3.5-dev10~17 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=ce789e01bff83bad7fb21d23030759e460ab01e7;p=haproxy.git BUG/MINOR: thread: don't turn reversed thread ranges into "even" parse_thread_set() checks that the last thread number of a range is within the permitted limits, but not that it is greater than or equal to the first one. When storing the set, "max < min" is the internal encoding of "all" (max=0), "odd" (max=-1) and "even" (max=-2), so any range written in reverse order such as "thread 4-2" or "thread 1/4-2" on a "bind" line was silently accepted and stored as "even" (memset 0xaa). With "nbthread 4", "thread 4-2" binds the listener to threads 2 and 4 instead of threads 2 to 4, and "thread 4-1" also gives threads 2 and 4. There is no warning, so the only visible effect is that some threads never accept connections on that listener, which is easy to miss and hard to diagnose. The other range parsers ("cpu-map", "process" via parse_process_number(), and the cpuset parser) swap a reversed range, so let's do the same here. This keeps configurations that rely on such ranges working, with the threads the user wrote. A reg-test is added to check that "2-4", "4-2" and "1/4-2" give the same thread mask. This bug was introduced with the thread_set API in 2.8 (commit bef43dfa6 "MINOR: thread: add a simple thread_set API"), so this fix may be backported to all stable branches down to 2.8. --- diff --git a/src/thread.c b/src/thread.c index aacae3c26..56b1dc2cb 100644 --- a/src/thread.c +++ b/src/thread.c @@ -2057,6 +2057,17 @@ int parse_thread_set(const char *arg, struct thread_set *ts, char **err) set, is_rel ? MAX_THREADS_PER_GROUP : MAX_THREADS); return -1; } + + /* a range given in reverse order is accepted and + * swapped, as done for "cpu-map" and "process". + * Otherwise max < min would be stored as "all", + * "odd" or "even" below. + */ + if (max < min) { + v = min; + min = max; + max = v; + } } /* here sep points to the first non-digit after the thread spec,