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>
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
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;
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 */