From: Willy Tarreau Date: Fri, 9 Oct 2020 13:47:17 +0000 (+0200) Subject: MEDIUM: listener: let do_unbind_listener() decide whether to close or not X-Git-Tag: v2.3-dev6~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=374e9af35;p=thirdparty%2Fhaproxy.git MEDIUM: listener: let do_unbind_listener() decide whether to close or not The listener contains all the information needed to decide to close on unbind or not. The rule is the following (when we're not stopping): - worker process unbinding from a worker's FD with socket transfer enabled => keep - master process unbinding from a master's inherited FD => keep - master process unbinding from a master's FD => close - master process unbinding from a worker's FD => close - worker process unbinding from a master's FD => close - worker process unbinding from a worker's FD => close Let's translate that into the function and stop using the do_close argument that is a bit obscure for callers. It was not yet removed to ease code testing. --- diff --git a/src/listener.c b/src/listener.c index 92463534b9..5002879dce 100644 --- a/src/listener.c +++ b/src/listener.c @@ -581,14 +581,32 @@ void do_unbind_listener(struct listener *listener, int do_close) } out_close: - if (do_close) { - listener->rx.flags &= ~RX_F_BOUND; - if (listener->rx.fd != -1) - fd_delete(listener->rx.fd); - listener->rx.fd = -1; - if (listener->state > LI_ASSIGNED) - listener_set_state(listener, LI_ASSIGNED); - } + /* There are a number of situations where we prefer to keep the FD and + * not to close it (unless we're stopping, of course): + * - worker process unbinding from a worker's FD with socket transfer enabled => keep + * - master process unbinding from a master's inherited FD => keep + * - master process unbinding from a master's FD => close + * - master process unbinding from a worker's FD => close + * - worker process unbinding from a master's FD => close + * - worker process unbinding from a worker's FD => close + */ + + if (!stopping && !master && + !(listener->options & LI_O_MWORKER) && + (global.tune.options & GTUNE_SOCKET_TRANSFER)) + return; + + if (!stopping && master && + listener->options & LI_O_MWORKER && + listener->rx.flags & RX_F_INHERITED) + return; + + listener->rx.flags &= ~RX_F_BOUND; + if (listener->rx.fd != -1) + fd_delete(listener->rx.fd); + listener->rx.fd = -1; + if (listener->state > LI_ASSIGNED) + listener_set_state(listener, LI_ASSIGNED); } /* This function closes the listening socket for the specified listener,