]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: fd: Take the fd_mig_lock when closing if no DWCAS is available.
authorOlivier Houchard <cognet@ci0.org>
Thu, 25 Mar 2021 00:38:54 +0000 (01:38 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 25 Mar 2021 06:34:35 +0000 (07:34 +0100)
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().

src/fd.c

index b3ae2c40b8fb4751a4795eda979fad1e2f2a70d2..f206d2a621211ada4d9bf74937d50ebc61468809 100644 (file)
--- a/src/fd.c
+++ b/src/fd.c
@@ -328,6 +328,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.
  */
@@ -350,15 +354,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.