MINOR: muxes: Pass the context of the mux to destroy() instead of the connection
It is mandatory to handle mux upgrades, because during a mux upgrade, the connection will be reassigned to another multiplexer. So when the old one is destroyed, it does not own the connection anymore. Or in other words, conn->ctx does not point to the old mux's context when its destroy() callback is called. So we now rely on the multiplexer context do destroy it instead of the connection. In addition, h1_release() and h2_release() have also been updated in the same way.
This commit is contained in:
parent
51f73eb11a
commit
73c1207c71
|
@ -126,7 +126,7 @@ static inline int session_check_idle_conn(struct session *sess, struct connectio
|
|||
conn->owner = NULL;
|
||||
if (!srv_add_to_idle_list(objt_server(conn->target), conn)) {
|
||||
/* The server doesn't want it, let's kill the connection right away */
|
||||
conn->mux->destroy(conn);
|
||||
conn->mux->destroy(conn->ctx);
|
||||
return -1;
|
||||
} else
|
||||
conn->flags &= ~CO_FL_SESS_IDLE;
|
||||
|
|
|
@ -346,7 +346,7 @@ struct mux_ops {
|
|||
int (*unsubscribe)(struct conn_stream *cs, int event_type, void *param); /* Unsubscribe to events */
|
||||
int (*avail_streams)(struct connection *conn); /* Returns the number of streams still available for a connection */
|
||||
int (*used_streams)(struct connection *conn); /* Returns the number of streams in use on a connection. */
|
||||
void (*destroy)(struct connection *conn); /* Let the mux know one of its users left, so it may have to disappear */
|
||||
void (*destroy)(void *ctx); /* Let the mux know one of its users left, so it may have to disappear */
|
||||
void (*reset)(struct connection *conn); /* Reset the mux, because we're re-trying to connect */
|
||||
const struct cs_info *(*get_cs_info)(struct conn_stream *cs); /* Return info on the specified conn_stream or NULL if not defined */
|
||||
unsigned int flags; /* some flags characterizing the mux's capabilities (MX_FL_*) */
|
||||
|
|
|
@ -1371,7 +1371,7 @@ int connect_server(struct stream *s)
|
|||
old_conn->owner = sess;
|
||||
if (!session_add_conn(sess, old_conn, old_conn->target)) {
|
||||
old_conn->owner = NULL;
|
||||
old_conn->mux->destroy(old_conn);
|
||||
old_conn->mux->destroy(old_conn->ctx);
|
||||
} else
|
||||
session_check_idle_conn(sess, old_conn);
|
||||
}
|
||||
|
@ -1427,7 +1427,7 @@ int connect_server(struct stream *s)
|
|||
srv_conn->owner = NULL;
|
||||
if (srv_conn->mux && !srv_add_to_idle_list(objt_server(srv_conn->target), srv_conn))
|
||||
/* The server doesn't want it, let's kill the connection right away */
|
||||
srv_conn->mux->destroy(srv_conn);
|
||||
srv_conn->mux->destroy(srv_conn->ctx);
|
||||
srv_conn = NULL;
|
||||
|
||||
}
|
||||
|
|
22
src/mux_h1.c
22
src/mux_h1.c
|
@ -438,13 +438,12 @@ static int h1_init(struct connection *conn, struct proxy *proxy, struct session
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* release function for a connection. This one should be called to free all
|
||||
* resources allocated to the mux.
|
||||
/* release function. This one should be called to free all resources allocated
|
||||
* to the mux.
|
||||
*/
|
||||
static void h1_release(struct connection *conn)
|
||||
static void h1_release(struct h1c *h1c)
|
||||
{
|
||||
struct h1c *h1c = conn->ctx;
|
||||
struct connection *conn = h1c->conn;
|
||||
|
||||
if (h1c) {
|
||||
if (!LIST_ISEMPTY(&h1c->buf_wait.list)) {
|
||||
|
@ -1867,7 +1866,7 @@ static int h1_process(struct h1c * h1c)
|
|||
return 0;
|
||||
|
||||
release:
|
||||
h1_release(conn);
|
||||
h1_release(h1c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1936,13 +1935,14 @@ static struct task *h1_timeout_task(struct task *t, void *context, unsigned shor
|
|||
if (h1c->h1s && h1c->h1s->cs)
|
||||
h1c->flags |= H1C_F_CS_ERROR;
|
||||
else
|
||||
h1_release(h1c->conn);
|
||||
h1_release(h1c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
/* functions below are used by the streams */
|
||||
/*******************************************/
|
||||
|
||||
/*
|
||||
* Attach a new stream to a connection
|
||||
* (Used for outgoing connections)
|
||||
|
@ -1984,12 +1984,12 @@ static const struct conn_stream *h1_get_first_cs(const struct connection *conn)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void h1_destroy(struct connection *conn)
|
||||
static void h1_destroy(void *ctx)
|
||||
{
|
||||
struct h1c *h1c = conn->ctx;
|
||||
struct h1c *h1c = ctx;
|
||||
|
||||
if (!h1c->h1s)
|
||||
h1_release(conn);
|
||||
h1_release(h1c);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2065,7 +2065,7 @@ static void h1_detach(struct conn_stream *cs)
|
|||
/* We don't want to close right now unless the connection is in error */
|
||||
if ((h1c->flags & (H1C_F_CS_ERROR|H1C_F_CS_SHUTDOWN)) ||
|
||||
(h1c->conn->flags & CO_FL_ERROR) || !h1c->conn->owner)
|
||||
h1_release(h1c->conn);
|
||||
h1_release(h1c);
|
||||
else {
|
||||
tasklet_wakeup(h1c->wait_event.task);
|
||||
if (h1c->task) {
|
||||
|
|
22
src/mux_h2.c
22
src/mux_h2.c
|
@ -614,12 +614,12 @@ static inline struct h2s *h2c_st_by_id(struct h2c *h2c, int id)
|
|||
return container_of(node, struct h2s, by_id);
|
||||
}
|
||||
|
||||
/* release function for a connection. This one should be called to free all
|
||||
* resources allocated to the mux.
|
||||
/* release function. This one should be called to free all resources allocated
|
||||
* to the mux.
|
||||
*/
|
||||
static void h2_release(struct connection *conn)
|
||||
static void h2_release(struct h2c *h2c)
|
||||
{
|
||||
struct h2c *h2c = conn->ctx;
|
||||
struct connection *conn = h2c->conn;
|
||||
|
||||
if (h2c) {
|
||||
hpack_dht_free(h2c->ddht);
|
||||
|
@ -2845,7 +2845,7 @@ static int h2_process(struct h2c *h2c)
|
|||
|
||||
if (eb_is_empty(&h2c->streams_by_id)) {
|
||||
/* no more stream, kill the connection now */
|
||||
h2_release(conn);
|
||||
h2_release(h2c);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -2930,7 +2930,7 @@ static struct task *h2_timeout_task(struct task *t, void *context, unsigned shor
|
|||
* the last stream closes.
|
||||
*/
|
||||
if (eb_is_empty(&h2c->streams_by_id))
|
||||
h2_release(h2c->conn);
|
||||
h2_release(h2c);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2985,12 +2985,12 @@ static const struct conn_stream *h2_get_first_cs(const struct connection *conn)
|
|||
/*
|
||||
* Destroy the mux and the associated connection, if it is no longer used
|
||||
*/
|
||||
static void h2_destroy(struct connection *conn)
|
||||
static void h2_destroy(void *ctx)
|
||||
{
|
||||
struct h2c *h2c = conn->ctx;
|
||||
struct h2c *h2c = ctx;
|
||||
|
||||
if (eb_is_empty(&h2c->streams_by_id))
|
||||
h2_release(h2c->conn);
|
||||
h2_release(h2c);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3082,7 +3082,7 @@ static void h2_detach(struct conn_stream *cs)
|
|||
*/
|
||||
if (h2c_is_dead(h2c)) {
|
||||
/* no more stream will come, kill it now */
|
||||
h2_release(h2c->conn);
|
||||
h2_release(h2c);
|
||||
}
|
||||
else if (h2c->task) {
|
||||
if (eb_is_empty(&h2c->streams_by_id) || b_data(&h2c->mbuf)) {
|
||||
|
@ -3248,7 +3248,7 @@ static struct task *h2_deferred_shut(struct task *t, void *ctx, unsigned short s
|
|||
h2s_destroy(h2s);
|
||||
|
||||
if (h2c_is_dead(h2c))
|
||||
h2_release(h2c->conn);
|
||||
h2_release(h2c);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
11
src/mux_pt.c
11
src/mux_pt.c
|
@ -166,13 +166,14 @@ static const struct conn_stream *mux_pt_get_first_cs(const struct connection *co
|
|||
return cs;
|
||||
}
|
||||
|
||||
/* Destroy the mux and the associated connection, if no longer used */
|
||||
static void mux_pt_destroy_meth(struct connection *conn)
|
||||
/* Destroy the mux and the associated connection if still attached to this mux
|
||||
* and no longer used */
|
||||
static void mux_pt_destroy_meth(void *ctx)
|
||||
{
|
||||
struct mux_pt_ctx *ctx = conn->ctx;
|
||||
struct mux_pt_ctx *pt = ctx;
|
||||
|
||||
if (!(ctx->cs))
|
||||
mux_pt_destroy(ctx);
|
||||
if (!(pt->cs))
|
||||
mux_pt_destroy(pt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -5317,7 +5317,7 @@ struct task *srv_cleanup_toremove_connections(struct task *task, void *context,
|
|||
|
||||
while ((conn = LIST_POP_LOCKED(&toremove_connections[tid],
|
||||
struct connection *, list)) != NULL) {
|
||||
conn->mux->destroy(conn);
|
||||
conn->mux->destroy(conn->ctx);
|
||||
}
|
||||
|
||||
return task;
|
||||
|
|
|
@ -74,7 +74,7 @@ void session_free(struct session *sess)
|
|||
vars_prune_per_sess(&sess->vars);
|
||||
conn = objt_conn(sess->origin);
|
||||
if (conn != NULL && conn->mux)
|
||||
conn->mux->destroy(conn);
|
||||
conn->mux->destroy(conn->ctx);
|
||||
list_for_each_entry_safe(srv_list, srv_list_back, &sess->srv_list, srv_list) {
|
||||
list_for_each_entry_safe(conn, conn_back, &srv_list->conn_list, session_list) {
|
||||
if (conn->mux) {
|
||||
|
@ -84,7 +84,7 @@ void session_free(struct session *sess)
|
|||
conn->owner = NULL;
|
||||
conn->flags &= ~CO_FL_SESS_IDLE;
|
||||
if (!srv_add_to_idle_list(objt_server(conn->target), conn))
|
||||
conn->mux->destroy(conn);
|
||||
conn->mux->destroy(conn->ctx);
|
||||
} else {
|
||||
/* We have a connection, but not yet an associated mux.
|
||||
* So destroy it now.
|
||||
|
|
Loading…
Reference in New Issue