diff --git a/include/haproxy/fd-t.h b/include/haproxy/fd-t.h index 433a3f3ae..64416d6dc 100644 --- a/include/haproxy/fd-t.h +++ b/include/haproxy/fd-t.h @@ -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 { diff --git a/src/fd.c b/src/fd.c index 4fbdaef45..079df15af 100644 --- a/src/fd.c +++ b/src/fd.c @@ -306,6 +306,9 @@ void fd_rm_from_fd_list(volatile struct fdlist *list, int fd, int off) */ 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); }