]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: fd: don't wait for tmask to stabilize if we're not in it.
authorOlivier Houchard <cognet@ci0.org>
Thu, 13 Apr 2023 14:12:38 +0000 (16:12 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 13 Apr 2023 16:04:46 +0000 (18:04 +0200)
In fd_update_events(), we loop until there's no bit in the running_mask
that is not in the thread_mask. Problem is, the thread sets its
running_mask bit before that loop, and so if 2 threads do the same, and
a 3rd one just closes the FD and sets the thread_mask to 0, then
running_mask will always be non-zero, and we will loop forever. This is
trivial to reproduce when using a DNS resolver that will just answer
"port unreachable", but could theoretically happen with other types of
file descriptors too.

To fix that, just don't bother looping if we're no longer in the
thread_mask, if that happens we know we won't have to take care of the
FD, anyway.

This should be backported to 2.7, 2.6 and 2.5.

src/fd.c

index 4c1ad5771f8a454c0c9b492672d692e6700eead9..9d34315cbe708fbdd4085c75944ad6682f247fe1 100644 (file)
--- a/src/fd.c
+++ b/src/fd.c
@@ -663,7 +663,7 @@ int fd_update_events(int fd, uint evts)
                rmask = _HA_ATOMIC_LOAD(&fdtab[fd].running_mask);
                tmask = _HA_ATOMIC_LOAD(&fdtab[fd].thread_mask);
                rmask &= ~ti->ltid_bit;
-       } while (rmask & ~tmask);
+       } while ((rmask & ~tmask) && (tmask & ti->ltid_bit));
 
        /* Now tmask is stable. Do nothing if the FD was taken over under us */