From 20b622e04b27e76f7b4be0c09b435e8799143d75 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 21 Oct 2021 21:31:42 +0200 Subject: [PATCH] MINOR: connection: add a new CO_FL_WANT_DRAIN flag to force drain on close 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. --- include/haproxy/connection-t.h | 2 +- include/haproxy/connection.h | 2 ++ src/sock.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 0ba8555ff..68ab91ae8 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -131,7 +131,7 @@ enum { CO_FL_CTRL_READY = 0x00000100, /* FD was registered, fd_delete() needed */ CO_FL_XPRT_READY = 0x00000200, /* xprt_start() done, xprt can be used */ - /* 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 diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index 17dad4bda..7c970e2bd 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -174,6 +174,8 @@ static inline void conn_ctrl_init(struct connection *conn) static inline void conn_ctrl_close(struct connection *conn) { if (!conn->xprt && (conn->flags & CO_FL_CTRL_READY)) { + if ((conn->flags & (CO_FL_WANT_DRAIN | CO_FL_SOCK_RD_SH)) == CO_FL_WANT_DRAIN) + conn_ctrl_drain(conn); conn->flags &= ~CO_FL_CTRL_READY; if (conn->ctrl->ctrl_close) conn->ctrl->ctrl_close(conn); diff --git a/src/sock.c b/src/sock.c index d05cf7e69..e546d8f4a 100644 --- a/src/sock.c +++ b/src/sock.c @@ -836,7 +836,7 @@ int sock_drain(struct connection *conn) if (fdtab[fd].state & (FD_POLL_ERR|FD_POLL_HUP)) goto shut; - if (!fd_recv_ready(fd)) + if (!(conn->flags & CO_FL_WANT_DRAIN) && !fd_recv_ready(fd)) return 0; /* no drain function defined, use the generic one */