MINOR: connection: add a new CO_FL_WANT_DRAIN flag to force drain on close
authorWilly Tarreau <w@1wt.eu>
Thu, 21 Oct 2021 19:31:42 +0000 (21:31 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 23 Nov 2021 15:34:07 +0000 (16:34 +0100)
Sometimes we'd like to do our best to drain pending data before closing
in order to save the peer from risking to receive an RST on close.

This adds a new connection flag CO_FL_WANT_DRAIN that is used to
trigger a call to conn_ctrl_drain() from conn_ctrl_close(), and the
sock_drain() function ignores fd_recv_ready() if this flag is set,
in order to catch latest data. It's not used for now.

(cherry picked from commit 20b622e04b27e76f7b4be0c09b435e8799143d75)
[Cf: On previous versions, conn_sock_drain() must be used instead of
     conn_ctrl_drain()]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit b17952cec409252817d09b95a1a97ffaff895fe9)
[Cf: As expected, conn_sock_drain() was used instead of
     conn_ctrl_drain(). Because sock_drain() does not exist on the 2.3,
     conn_sock_drain() was updated to do nothing when CO_FL_WANT_DRAIN flag
     is not set]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

include/haproxy/connection-t.h
include/haproxy/connection.h
src/connection.c

index 401d756..f0810de 100644 (file)
@@ -127,7 +127,7 @@ enum {
        CO_FL_CTRL_READY    = 0x00000100, /* FD was registered, fd_delete() needed */
        CO_FL_XPRT_READY    = 0x00000200, /* xprt_init() done, xprt_close() needed */
 
-       /* unused : 0x00000400 */
+       CO_FL_WANT_DRAIN    = 0x00000400, /* try to drain pending data when closing */
 
        /* This flag is used by data layers to indicate they had to stop
         * receiving data because a buffer was full. The connection handler
index be41362..3a154a8 100644 (file)
@@ -144,6 +144,8 @@ static inline void conn_ctrl_init(struct connection *conn)
 static inline void conn_ctrl_close(struct connection *conn)
 {
        if ((conn->flags & (CO_FL_XPRT_READY|CO_FL_CTRL_READY)) == CO_FL_CTRL_READY) {
+               if ((conn->flags & (CO_FL_WANT_DRAIN | CO_FL_SOCK_RD_SH)) == CO_FL_WANT_DRAIN)
+                       conn_sock_drain(conn);
                fd_delete(conn->handle.fd);
                conn->handle.fd = DEAD_FD_MAGIC;
                conn->flags &= ~CO_FL_CTRL_READY;
index d64e941..4361bfc 100644 (file)
@@ -417,7 +417,7 @@ int conn_sock_drain(struct connection *conn)
        if (fdtab[conn->handle.fd].ev & (FD_POLL_ERR|FD_POLL_HUP))
                goto shut;
 
-       if (!fd_recv_ready(conn->handle.fd))
+       if (!(conn->flags & CO_FL_WANT_DRAIN) && !fd_recv_ready(conn->handle.fd))
                return 0;
 
        /* no drain function defined, use the generic one */