From: Amaury Denoyelle Date: Mon, 14 Aug 2023 08:52:50 +0000 (+0200) Subject: MINOR: proto_reverse_connect: handle early error before reversal X-Git-Tag: v2.9-dev4~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b130f8dbc343640fd3867168f9e8f0c16ad5e9d0;p=thirdparty%2Fhaproxy.git MINOR: proto_reverse_connect: handle early error before reversal An error can occured on a reverse connection before accept is completed. In this case, no parent session can be notified. Instead, wake up the receiver task on conn_create_mux(). As a counterpart to this, receiver task is extended to match CO_FL_ERROR flag on pending connection. In this case, the onnection is freed. The task is then requeued with a 1 second delay to start a new reverse connection attempt. --- diff --git a/src/connection.c b/src/connection.c index 5ebc1d90a9..8a7db31637 100644 --- a/src/connection.c +++ b/src/connection.c @@ -91,8 +91,24 @@ int conn_create_mux(struct connection *conn) return 0; fail: /* let the upper layer know the connection failed */ - if (sc) + if (sc) { sc->app_ops->wake(sc); + } + else if (conn_reverse_in_preconnect(conn)) { + struct listener *l = conn_active_reverse_listener(conn); + + /* If mux init failed, consider connection on error. + * This is necessary to ensure connection is freed by + * proto-reverse-connect receiver task. + */ + if (!conn->mux) + conn->flags |= CO_FL_ERROR; + + /* If connection is interrupted without CO_FL_ERROR, receiver task won't free it. */ + BUG_ON(!(conn->flags & CO_FL_ERROR)); + + task_wakeup(l->rx.reverse_connect.task, TASK_WOKEN_ANY); + } return -1; } else return conn_complete_session(conn); @@ -543,6 +559,8 @@ void conn_free(struct connection *conn) /* Receiver must reference a reverse connection as pending. */ BUG_ON(!l->rx.reverse_connect.pend_conn); l->rx.reverse_connect.pend_conn = NULL; + l->rx.reverse_connect.task->expire = MS_TO_TICKS(now_ms + 1000); + task_queue(l->rx.reverse_connect.task); } conn_force_unsubscribe(conn); diff --git a/src/proto_reverse_connect.c b/src/proto_reverse_connect.c index 1bbc70957e..6944d6c391 100644 --- a/src/proto_reverse_connect.c +++ b/src/proto_reverse_connect.c @@ -107,11 +107,22 @@ struct task *rev_process(struct task *task, void *ctx, unsigned int state) struct connection *conn = l->rx.reverse_connect.pend_conn; if (conn) { - /* Spurrious receiver task wake up when pend_conn is not ready/on error. */ - BUG_ON(!(conn->flags & CO_FL_REVERSED)); - /* A connection is ready to be accepted. */ - listener_accept(l); - l->rx.reverse_connect.task->expire = TICK_ETERNITY; + if (conn->flags & CO_FL_ERROR) { + conn_full_close(conn); + conn_free(conn); + l->rx.reverse_connect.pend_conn = NULL; + + /* Retry on 1s on error. */ + l->rx.reverse_connect.task->expire = MS_TO_TICKS(now_ms + 1000); + } + else { + /* Spurrious receiver task wake up when pend_conn is not ready/on error. */ + BUG_ON(!(conn->flags & CO_FL_REVERSED)); + + /* A connection is ready to be accepted. */ + listener_accept(l); + l->rx.reverse_connect.task->expire = TICK_ETERNITY; + } } else { /* No pending reverse connection, prepare a new one. Store it in the