]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: fd: support broadcasting updates for foreign groups in updt_fd_polling
authorWilly Tarreau <w@1wt.eu>
Fri, 15 Jul 2022 18:12:31 +0000 (20:12 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 15 Jul 2022 18:25:41 +0000 (20:25 +0200)
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

index 5a850d0915e35e314536a04864727347f23085c6..b4b3d7b48dfd68e2d1f15d0894ee22806fc84730 100644 (file)
--- 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;