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").
This commit is contained in:
Willy Tarreau 2022-07-15 20:12:31 +02:00
parent 1f947cb39e
commit cfdd20a0b2

View File

@ -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;