BUG/MINOR: proto_reverse_connect: fix FD leak on connection error

Listener using "rev@" address is responsible to setup connection and
reverse it using a server instance. If an error occured before reversal
is completed, proper freeing must be taken care of by the listener as no
session exists for this.

Currently, there is two locations where a connection is freed on error
before reversal inside reverse_connect protocol. Both of these were
incomplete as several function must be used to ensure connection is
properly freed. This commit fixes this by reusing the same cleaning
mechanism used inside H2 multiplexer.

One of the biggest drawback before this patch was that connection FD was
not properly removed from fdtab which caused a file-descriptor leak.

No need to backport this.
This commit is contained in:
Amaury Denoyelle 2023-09-29 16:04:21 +02:00
parent b3dcd59f8d
commit 6118590e95
1 changed files with 17 additions and 1 deletions

View File

@ -92,6 +92,15 @@ static struct connection *new_reverse_conn(struct listener *l, struct server *sr
err: err:
if (conn) { if (conn) {
conn_stop_tracking(conn);
conn_xprt_shutw(conn);
conn_xprt_close(conn);
conn_sock_shutw(conn, 0);
conn_ctrl_close(conn);
if (conn->destroy_cb)
conn->destroy_cb(conn);
/* Mark connection as non-reversable. This prevents conn_free() /* Mark connection as non-reversable. This prevents conn_free()
* to reschedule reverse_connect task on freeing a preconnect * to reschedule reverse_connect task on freeing a preconnect
* connection. * connection.
@ -137,7 +146,14 @@ struct task *rev_process(struct task *task, void *ctx, unsigned int state)
if (conn) { if (conn) {
if (conn->flags & CO_FL_ERROR) { if (conn->flags & CO_FL_ERROR) {
conn_full_close(conn); conn_stop_tracking(conn);
conn_xprt_shutw(conn);
conn_xprt_close(conn);
conn_sock_shutw(conn, 0);
conn_ctrl_close(conn);
if (conn->destroy_cb)
conn->destroy_cb(conn);
conn_free(conn); conn_free(conn);
/* conn_free() must report preconnect failure using rev_notify_preconn_err(). */ /* conn_free() must report preconnect failure using rev_notify_preconn_err(). */