From: Olivier Houchard Date: Wed, 8 Jul 2026 14:01:36 +0000 (+0200) Subject: MEDIUM: pollers: Only allow epoll when each tgroup has its fd table X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a39eb11afd7dcdb8af5f1f41f157882b6f6570cd;p=thirdparty%2Fhaproxy.git MEDIUM: pollers: Only allow epoll when each tgroup has its fd table Getting pollers such as select and poll to work when thread groups unshared their file descriptors would require to have per-thread groups arrays of file descriptors. Given making each thread group its own file descriptor table is done for performance reasons, and those pollers will never perform very well, this does not seem to be worth it. kqueue and evports would work, except that they are only implemented on OSes that do not provide the equivalent of the unshare() system call. So effectively, only epoll can be used as a poller when fds are not shared across thread groups. --- diff --git a/include/haproxy/fd-t.h b/include/haproxy/fd-t.h index a57fd6e8f..fcd71405a 100644 --- a/include/haproxy/fd-t.h +++ b/include/haproxy/fd-t.h @@ -231,6 +231,7 @@ struct polled_mask { #define HAP_POLL_F_RDHUP 0x00000001 /* the poller notifies of HUP with reads */ #define HAP_POLL_F_ERRHUP 0x00000002 /* the poller reports ERR and HUP */ +#define HAP_POLL_F_NO_FD_SHARING 0x00000004 /* the poller supports not sharing fds across thread groups */ struct poller { void *private; /* any private data for the poller */ diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 1f99e7ceb..5e205fe69 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -470,7 +470,7 @@ static void _do_register(void) p->name = "epoll"; p->pref = 300; - p->flags = HAP_POLL_F_ERRHUP; // note: RDHUP might be dynamically added + p->flags = HAP_POLL_F_ERRHUP | HAP_POLL_F_NO_FD_SHARING; // note: RDHUP might be dynamically added p->private = NULL; p->clo = __fd_clo; diff --git a/src/fd.c b/src/fd.c index c1f725029..7e106654e 100644 --- a/src/fd.c +++ b/src/fd.c @@ -1273,6 +1273,7 @@ int init_pollers() do { bp = NULL; +redo: for (p = 0; p < nbpollers; p++) if (!bp || (pollers[p].pref > bp->pref)) bp = &pollers[p]; @@ -1280,6 +1281,13 @@ int init_pollers() if (!bp || bp->pref == 0) break; + if ((global.tune.options & GTUNE_NO_TG_FD_SHARING) && + !(bp->flags & HAP_POLL_F_NO_FD_SHARING)) { + ha_alert("Can't use poller '%s' with per-thread-group FD tables\n", bp->name); + bp->pref = 0; + goto redo; + } + if (bp->init(bp)) { memcpy(&cur_poller, bp, sizeof(*bp)); return 1;