diff --git a/src/connection.c b/src/connection.c index 15fac3126..8acf04c9d 100644 --- a/src/connection.c +++ b/src/connection.c @@ -555,6 +555,18 @@ static void conn_backend_deinit(struct connection *conn) pool_free(pool_head_conn_hash_node, conn->hash_node); conn->hash_node = NULL; + /* Remove from BE purge list. Necessary if conn already scheduled for + * purge but finally freed before by another code path. + */ + MT_LIST_DELETE(&conn->toremove_list); +} + +/* Ensure frontend connection is removed from its lists. This must be + * performed before freeing or reversing a connection. + */ +static void conn_frontend_deinit(struct connection *conn) +{ + LIST_DEL_INIT(&conn->stopping_list); } /* Tries to allocate a new connection and initialized its main fields. The @@ -594,14 +606,8 @@ void conn_free(struct connection *conn) if (conn_is_back(conn)) conn_backend_deinit(conn); - - /* Remove the conn from toremove_list. - * - * This is needed to prevent a double-free in case the connection was - * already scheduled from cleaning but is freed before via another - * call. - */ - MT_LIST_DELETE(&conn->toremove_list); + else + conn_frontend_deinit(conn); sockaddr_free(&conn->src); sockaddr_free(&conn->dst); @@ -2961,7 +2967,7 @@ int conn_reverse(struct connection *conn) struct server *srv = objt_server(conn->reverse.target); BUG_ON(!srv); - LIST_DEL_INIT(&conn->stopping_list); + conn_frontend_deinit(conn); if (conn_backend_init(conn)) return 1; diff --git a/src/mux_h1.c b/src/mux_h1.c index 86de1149c..defcada21 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -1412,9 +1412,6 @@ static void h1_release(struct h1c *h1c) pool_free(pool_head_h1c, h1c); if (conn) { - if (!conn_is_back(conn)) - LIST_DEL_INIT(&conn->stopping_list); - conn->mux = NULL; conn->ctx = NULL; TRACE_DEVEL("freeing conn", H1_EV_H1C_END, conn); diff --git a/src/mux_h2.c b/src/mux_h2.c index fe68a4cdf..d656e43bc 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -1516,9 +1516,6 @@ static void h2_release(struct h2c *h2c) pool_free(pool_head_h2c, h2c); if (conn) { - if (!conn_is_back(conn)) - LIST_DEL_INIT(&conn->stopping_list); - conn->mux = NULL; conn->ctx = NULL; TRACE_DEVEL("freeing conn", H2_EV_H2C_END, conn); diff --git a/src/mux_quic.c b/src/mux_quic.c index 21f082770..1dd01534b 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3360,8 +3360,6 @@ static void qcc_release(struct qcc *qcc) pool_free(pool_head_qcc, qcc); if (conn) { - LIST_DEL_INIT(&conn->stopping_list); - conn->mux = NULL; conn->ctx = NULL;