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().
This commit is contained in:
Olivier Houchard 2021-03-25 01:38:54 +01:00 committed by Willy Tarreau
parent 2d4232901c
commit c23b33764e

View File

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