MINOR: fd: add a new FD_DISOWN flag to prevent from closing a deleted FD

Some FDs might be offered to some external code (external libraries)
which will deal with them until they close them. As such we must not
close them upon fd_delete() but we need to delete them anyway so that
they do not appear anymore in the fdtab. This used to be handled by
fd_remove() before 2.3 but we don't have this anymore.

This patch introduces a new flag FD_DISOWN to let fd_delete() know that
the core doesn't own the fd and it must not be closed upon removal from
the fd_tab. This way it's totally unregistered from the poller but still
open.

This patch must be backported on branches >= 2.3 because it will be
needed to fix a bug affecting SSL async. it should be adapted on 2.3
because state flags were stored in a different way (via bits in the
structure).

(cherry picked from commit f41a3f6762)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
This commit is contained in:
Emeric Brun 2022-07-01 17:31:25 +02:00 committed by Christopher Faulet
parent ac082b4194
commit 7e47164fe3
2 changed files with 7 additions and 1 deletions

View File

@ -69,6 +69,7 @@ enum {
#define FD_ET_POSSIBLE_BIT 19 /* edge-triggered is possible on this FD */
#define FD_EXPORTED_BIT 20 /* FD is exported and must not be closed */
#define FD_EXCL_SYSCALL_BIT 21 /* a syscall claims exclusivity on this FD */
#define FD_DISOWN_BIT 22 /* this fd will be closed by some external code */
/* and flag values */
@ -109,6 +110,7 @@ enum {
#define FD_ET_POSSIBLE (1U << FD_ET_POSSIBLE_BIT)
#define FD_EXPORTED (1U << FD_EXPORTED_BIT)
#define FD_EXCL_SYSCALL (1U << FD_EXCL_SYSCALL_BIT)
#define FD_DISOWN (1U << FD_DISOWN_BIT)
/* FD update status after fd_update_events() */
enum {

View File

@ -306,6 +306,9 @@ done:
*/
void _fd_delete_orphan(int fd)
{
uint fd_disown;
fd_disown = fdtab[fd].state & FD_DISOWN;
if (fdtab[fd].state & FD_LINGER_RISK) {
/* this is generally set when connecting to servers */
DISGUISE(setsockopt(fd, SOL_SOCKET, SO_LINGER,
@ -327,7 +330,8 @@ void _fd_delete_orphan(int fd)
/* perform the close() call last as it's what unlocks the instant reuse
* of this FD by any other thread.
*/
close(fd);
if (!fd_disown)
close(fd);
_HA_ATOMIC_DEC(&ha_used_fds);
}