]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: threads/config: drop absent threads from thread groups
authorWilly Tarreau <w@1wt.eu>
Fri, 17 Oct 2025 18:36:00 +0000 (20:36 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 17 Oct 2025 18:36:00 +0000 (20:36 +0200)
Thread groups can be assigned arbitrary thread ranges, but if the
mentioned threads do not exist, this causes crashes in listener_accept()
or some connections to be ignored. The reason is that the calculated
mask is derived from the thread group's enabled threads count. Examples:

  global
     nbthread 2
     thread-groups 2
     thread-group 1 1-64
     thread-group 2 65-128

  frontend f-crash
     bind :8001 thread 1/all

  frontend f-freeze
     bind :8002 thread 2/all

This commit removes missing threads, emits a warning when the thread
group just has less threads than requested, and an error when it is
left with no threads at all.

This must be backported to 3.1 since the issue is present there already.

src/thread.c

index 02929916c27bd518a81992295e830038e7182976..b5f5d7d97d8422e49640e4b5933fc7c8e5f78ee9 100644 (file)
@@ -1459,6 +1459,23 @@ int thread_map_to_groups()
                ha_thread_info[t].ltid_bit = 1UL << ha_thread_info[t].ltid;
        }
 
+       /* limit thread groups to existing threads only */
+       for (g = 0; g < global.nbtgroups; g++) {
+               if (ha_tgroup_info[g].base >= global.nbthread) {
+                       ha_alert("Thread-group %d only references non-existing threads (max=%d, requested %d-%d)\n",
+                                g + 1, global.nbthread, ha_tgroup_info[g].base + 1, ha_tgroup_info[g].base + ha_tgroup_info[g].count);
+                       return -1;
+               }
+
+               if (ha_tgroup_info[g].base + ha_tgroup_info[g].count > global.nbthread) {
+                       ha_warning("Reducing thread-group %d to %d threads (requested %d-%d, using %d-%d)\n",
+                                  g + 1, global.nbthread - ha_tgroup_info[g].base,
+                                  ha_tgroup_info[g].base + 1, ha_tgroup_info[g].base + ha_tgroup_info[g].count,
+                                  ha_tgroup_info[g].base + 1, global.nbthread);
+                       ha_tgroup_info[g].count = global.nbthread - ha_tgroup_info[g].base;
+               }
+       }
+
        m = 0;
        for (g = 0; g < global.nbtgroups; g++) {
                ha_tgroup_info[g].threads_enabled = nbits(ha_tgroup_info[g].count);