]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: backend: Do not always allow takeover across thread groups
authorOlivier Houchard <ohouchard@haproxy.com>
Thu, 2 Jul 2026 16:49:48 +0000 (18:49 +0200)
committerOlivier Houchard <cognet@ci0.org>
Thu, 30 Jul 2026 11:35:22 +0000 (13:35 +0200)
When we're running with separate file descriptor tables across thread
groups, do not allow connection takeover across thread groups, as the
connection would not be usable for that thread, anyway.

src/backend.c
src/fd.c

index ab1a8d9635f382a2a507f5c328cf7c8e359d1256..1c374676e25d16bd9e3504b7dc5b39a7d809aee6 100644 (file)
@@ -1406,7 +1406,8 @@ check_tgid:
 
        if (!found && (global.tune.tg_takeover == FULL_THREADGROUP_TAKEOVER ||
            (global.tune.tg_takeover == RESTRICTED_THREADGROUP_TAKEOVER &&
-           srv->flags & (SRV_F_RHTTP | SRV_F_STRICT_MAXCONN)))) {
+           srv->flags & (SRV_F_RHTTP | SRV_F_STRICT_MAXCONN))) &&
+           !(global.tune.options & GTUNE_NO_TG_FD_SHARING)) {
                curtgid = curtgid + 1;
                if (curtgid == global.nbtgroups + 1)
                        curtgid = 1;
@@ -1513,14 +1514,26 @@ static int
 kill_random_idle_conn(struct server *srv)
 {
        struct connection *conn = NULL;
+       uint base = 0, count = global.nbthread, start = tid;
        int i;
        int curtid;
        /* No idle conn, then there is nothing we can do at this point */
 
        if (srv->curr_idle_conns == 0)
                return -1;
-       for (i = 0; i < global.nbthread; i++) {
-               curtid = (i + tid) % global.nbthread;
+
+       /*
+        *  with per-thread-group fd tables, a connection cannot be taken over
+        * from a thread of another group, as its fd is only valid in the
+        * owner group's table, so only consider our own group's threads.
+        */
+       if (global.tune.options & GTUNE_NO_TG_FD_SHARING) {
+               base = tg->base;
+               count = tg->count;
+               start = ti->ltid;
+       }
+       for (i = 0; i < count; i++) {
+               curtid = base + (start + i) % count;
 
                if (HA_SPIN_TRYLOCK(IDLE_CONNS_LOCK, &idle_conns[curtid].idle_conns_lock) != 0)
                        continue;
index 66e256cd6930a9b056db81fedc6c1e8945121df5..c1f72502928a643d38c0afebbecac947111bfa65 100644 (file)
--- a/src/fd.c
+++ b/src/fd.c
@@ -552,6 +552,8 @@ int fd_takeover(int fd, void *expected_owner)
 
        /* We're taking a connection from a different thread group */
        if ((fdtab[fd].refc_tgid & 0x7fff) != tgid) {
+               BUG_ON(global.tune.options & GTUNE_NO_TG_FD_SHARING);
+
                changing_tgid = 1;
 
                old_tgid = fd_tgid(fd);