]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: receivers: add an rx_unbind() method in the protocols
authorWilly Tarreau <w@1wt.eu>
Fri, 9 Oct 2020 14:32:08 +0000 (16:32 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 9 Oct 2020 16:44:36 +0000 (18:44 +0200)
This is used as a generic way to unbind a receiver at the end of
do_unbind_listener(). This allows to considerably simplify that function
since we can now let the protocol perform the cleanup. The generic code
was moved to sock.c, along with the conditional rx_disable() call. Now
the code also supports that the ->disable() function of the protocol
which acts on the listener performs the close itself and adjusts the
RX_F_BUOND flag accordingly.

include/haproxy/protocol-t.h
include/haproxy/sock.h
src/listener.c
src/proto_sockpair.c
src/proto_tcp.c
src/proto_udp.c
src/proto_uxst.c
src/sock.c

index c5b93ed2a6b2d0eded4e41205b8ed74d6ece334c..7411d6d3d0ac0bc4556778be528f0b8531dc6d02 100644 (file)
@@ -95,6 +95,7 @@ struct protocol {
        /* functions acting on the receiver */
        void (*rx_enable)(struct receiver *rx);         /* enable receiving on the receiver */
        void (*rx_disable)(struct receiver *rx);        /* disable receiving on the receiver */
+       void (*rx_unbind)(struct receiver *rx);         /* unbind the receiver, most often closing the FD */
        int (*rx_suspend)(struct receiver *rx);         /* temporarily suspend this receiver for a soft restart */
        int (*rx_resume)(struct receiver *rx);          /* try to resume a temporarily suspended receiver */
 
index 70002329249aba01aee29d993f619e4b963b5375..c43f4d88b92594bb04ad87dfedbd344f3271e4bd 100644 (file)
@@ -35,6 +35,7 @@ extern struct xfer_sock_list *xfer_sock_list;
 int sock_create_server_socket(struct connection *conn);
 void sock_enable(struct receiver *rx);
 void sock_disable(struct receiver *rx);
+void sock_unbind(struct receiver *rx);
 int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 int sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 int sock_get_old_sockets(const char *unixsocket);
index d28b8da4bd32d853827086601655ccea37790a19..b1c64371b1d173bb5269ac1590d3b38a74168c12 100644 (file)
@@ -543,7 +543,8 @@ void dequeue_proxy_listeners(struct proxy *px)
  * LI_ASSIGNED state, except if the FD is not closed, in which case it may
  * remain in LI_LISTEN. Depending on the process' status (master or worker),
  * the listener's bind options and the receiver's origin, it may or may not
- * close the receiver's FD. Must be called with the lock held.
+ * close the receiver's FD, according to what is provided at the receiver
+ * level. Must be called with the lock held.
  */
 void do_unbind_listener(struct listener *listener)
 {
@@ -557,40 +558,18 @@ void do_unbind_listener(struct listener *listener)
                goto out_close;
        }
 
-       if (listener->state >= LI_PAUSED) {
-               if (listener->state >= LI_READY) {
-                       listener->rx.proto->disable(listener);
+       if (listener->state >= LI_READY) {
+               listener->rx.proto->disable(listener);
+               if (listener->rx.flags & RX_F_BOUND)
                        listener_set_state(listener, LI_LISTEN);
-               }
-               listener->rx.proto->rx_disable(&listener->rx);
        }
 
  out_close:
-       /* 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->rx.flags & RX_F_MWORKER) &&
-           (global.tune.options & GTUNE_SOCKET_TRANSFER))
-               return;
-
-       if (!stopping && master &&
-           listener->rx.flags & RX_F_MWORKER &&
-           listener->rx.flags & RX_F_INHERITED)
-               return;
+       if (listener->rx.flags & RX_F_BOUND)
+               listener->rx.proto->rx_unbind(&listener->rx);
 
-       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)
+       /* we may have to downgrade the listener if the rx was closed */
+       if (!(listener->rx.flags & RX_F_BOUND) && listener->state > LI_ASSIGNED)
                listener_set_state(listener, LI_ASSIGNED);
 }
 
index f43aa8229e6f26bbf5893d11fc633fd159e77def..9eac2cc2c16bc9e17e75f180964fe8cf1fee7739 100644 (file)
@@ -72,6 +72,7 @@ static struct protocol proto_sockpair = {
        .listen = sockpair_bind_listener,
        .enable = sockpair_enable_listener,
        .disable = sockpair_disable_listener,
+       .rx_unbind = sock_unbind,
        .rx_enable = sock_enable,
        .rx_disable = sock_disable,
        .accept = &listener_accept,
index b12cf724b0cbed0c1df35bc470dac29bdcda2d29..33eacbce0be6d2cdf6d8b1390e4cf526a9a00577 100644 (file)
@@ -66,6 +66,7 @@ static struct protocol proto_tcpv4 = {
        .disable = tcp_disable_listener,
        .rx_enable = sock_enable,
        .rx_disable = sock_disable,
+       .rx_unbind = sock_unbind,
        .rx_suspend = tcp_suspend_receiver,
        .rx_resume = tcp_resume_receiver,
        .accept = &listener_accept,
@@ -90,6 +91,7 @@ static struct protocol proto_tcpv6 = {
        .disable = tcp_disable_listener,
        .rx_enable = sock_enable,
        .rx_disable = sock_disable,
+       .rx_unbind = sock_unbind,
        .rx_suspend = tcp_suspend_receiver,
        .rx_resume = tcp_resume_receiver,
        .accept = &listener_accept,
index 1dc731778eef164592fd55fff6340169a1af17ab..8c53c6201bc50eea20177c0107a1c1a873fcaaed 100644 (file)
@@ -62,6 +62,7 @@ static struct protocol proto_udp4 = {
        .disable = udp_disable_listener,
        .rx_enable = sock_enable,
        .rx_disable = sock_disable,
+       .rx_unbind = sock_unbind,
        .rx_suspend = udp_suspend_receiver,
        .rx_resume = udp_resume_receiver,
        .receivers = LIST_HEAD_INIT(proto_udp4.receivers),
@@ -84,6 +85,7 @@ static struct protocol proto_udp6 = {
        .disable = udp_disable_listener,
        .rx_enable = sock_enable,
        .rx_disable = sock_disable,
+       .rx_unbind = sock_unbind,
        .rx_suspend = udp_suspend_receiver,
        .rx_resume = udp_resume_receiver,
        .receivers = LIST_HEAD_INIT(proto_udp6.receivers),
index 250c630189311ff09e33895f467493574f78fb66..77415867afc339743c563cc883bd15148123556a 100644 (file)
@@ -61,6 +61,7 @@ static struct protocol proto_unix = {
        .disable = uxst_disable_listener,
        .rx_enable = sock_enable,
        .rx_disable = sock_disable,
+       .rx_unbind = sock_unbind,
        .rx_suspend = uxst_suspend_receiver,
        .accept = &listener_accept,
        .connect = &uxst_connect_server,
index c06a28149e79b929dbdd180c97788e82b9ddbc02..4ef0076900c27713bf149223d4ad16c53da03af0 100644 (file)
@@ -73,6 +73,37 @@ void sock_disable(struct receiver *rx)
                fd_stop_recv(rx->fd);
 }
 
+/* stops, unbinds and possibly closes the FD associated with receiver rx */
+void sock_unbind(struct receiver *rx)
+{
+       /* 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 (rx->flags & RX_F_BOUND)
+               rx->proto->rx_disable(rx);
+
+       if (!stopping && !master &&
+           !(rx->flags & RX_F_MWORKER) &&
+           (global.tune.options & GTUNE_SOCKET_TRANSFER))
+               return;
+
+       if (!stopping && master &&
+           rx->flags & RX_F_MWORKER &&
+           rx->flags & RX_F_INHERITED)
+               return;
+
+       rx->flags &= ~RX_F_BOUND;
+       if (rx->fd != -1)
+               fd_delete(rx->fd);
+       rx->fd = -1;
+}
+
 /*
  * Retrieves the source address for the socket <fd>, with <dir> indicating
  * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of