From cfdd20a0b2d3c49db91a37f8b7b65e5ca5dd2e2b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 15 Jul 2022 20:12:31 +0200 Subject: [PATCH] MEDIUM: fd: support broadcasting updates for foreign groups in updt_fd_polling We're still facing the situation where it's impossible to update an FD for a foreign group. That's of particular concern when disabling/enabling listeners (e.g. pause/resume on signals) since we don't decide which thread gets the signal and it needs to process all listeners at once. Fortunately, not that much is unprotected in FDs. This patch adds a test for tgid's equality in updt_fd_polling() so that if a change is applied for a foreing group, then it's detected and taken care of separately. The method consists in forcing the update on all bound threads in this group, adding it to the group's update_list, and sending a wake-up as would be done for a remote thread in the local group, except that this is done by grabbing a reference to the FD's tgid. Thanks to this, SIGTTOU/SIGTTIN now work for nbtgroups > 1 (after that was temporarily broken by "MEDIUM: fd/poller: make the update-list per-group"). --- src/fd.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/fd.c b/src/fd.c index 5a850d0915..b4b3d7b48d 100644 --- a/src/fd.c +++ b/src/fd.c @@ -466,6 +466,36 @@ int fd_takeover(int fd, void *expected_owner) void updt_fd_polling(const int fd) { + uint tgrp = fd_take_tgid(fd); + + /* closed ? may happen */ + if (!tgrp) + return; + + if (unlikely(tgrp != tgid && tgrp <= MAX_TGROUPS)) { + /* Hmmm delivered an update for another group... That may + * happen on suspend/resume of a listener for example when + * the FD was not even marked for running. Let's broadcast + * the update. + */ + unsigned long update_mask = fdtab[fd].update_mask; + int thr; + + while (!_HA_ATOMIC_CAS(&fdtab[fd].update_mask, &update_mask, ha_tgroup_info[tgrp - 1].threads_enabled)) + __ha_cpu_relax(); + + fd_add_to_fd_list(&update_list[tgrp - 1], fd); + + thr = one_among_mask(fdtab[fd].thread_mask & tg->threads_enabled, statistical_prng_range(MAX_THREADS)); + thr += ha_tgroup_info[tgrp - 1].base; + wake_thread(thr); + + fd_drop_tgid(fd); + return; + } + + fd_drop_tgid(fd); + if (tg->threads_enabled == 1UL || (fdtab[fd].thread_mask & tg->threads_enabled) == ti->ltid_bit) { if (HA_ATOMIC_BTS(&fdtab[fd].update_mask, ti->ltid)) return; -- 2.39.5