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.
This commit is contained in:
Amaury Denoyelle 2023-08-14 10:52:50 +02:00
parent 47f502df5e
commit b130f8dbc3
2 changed files with 35 additions and 6 deletions

View File

@ -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);

View File

@ -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