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 <w@1wt.eu>
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 @@
_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 @@
*/
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.