From 5fbd555100827371046612ee31e5226af30e4ad6 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Thu, 25 Mar 2021 01:38:54 +0100 Subject: [PATCH] BUG/MEDIUM: fd: Take the fd_mig_lock when closing if no DWCAS is available. In fd_delete(), if we're running with no double-width cas, take the fd_mig_lock before setting thread_mask to 0 to make sure that another thread calling fd_set_running() won't miss the new value of thread_mask and set its bit in running_mask after we checked it. This should be backported to 2.2 as part of the series fixing fd_delete(). (cherry picked from commit c23b33764ea88587193472283c3e2d7a88448392) Signed-off-by: Willy Tarreau --- src/fd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/fd.c b/src/fd.c index b569bdc..0c4a796 100644 --- a/src/fd.c +++ b/src/fd.c @@ -327,6 +327,10 @@ void _fd_delete_orphan(int fd) _HA_ATOMIC_SUB(&ha_used_fds, 1); } +#ifndef HA_HAVE_CAS_DW +__decl_thread(__decl_rwlock(fd_mig_lock)); +#endif + /* Deletes an FD from the fdsets. The file descriptor is also closed, possibly * asynchronously. Only the owning thread may do this. */ @@ -349,15 +353,17 @@ void fd_delete(int fd) */ HA_ATOMIC_OR(&fdtab[fd].running_mask, tid_bit); +#ifndef HA_HAVE_CAS_DW + HA_RWLOCK_WRLOCK(OTHER_LOCK, &fd_mig_lock); +#endif HA_ATOMIC_STORE(&fdtab[fd].thread_mask, 0); +#ifndef HA_HAVE_CAS_DW + HA_RWLOCK_WRUNLOCK(OTHER_LOCK, &fd_mig_lock); +#endif if (fd_clr_running(fd) == 0) _fd_delete_orphan(fd); } -#ifndef HA_HAVE_CAS_DW -__decl_thread(__decl_rwlock(fd_mig_lock)); -#endif - /* * Take over a FD belonging to another thread. * unexpected_conn is the expected owner of the fd. -- 1.7.10.4