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).
#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 */
#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 {
*/
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,
/* 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);
}