]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: muxes: Pass the context of the mux to destroy() instead of the connection
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 8 Apr 2019 09:23:22 +0000 (11:23 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Apr 2019 20:06:53 +0000 (22:06 +0200)
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.

include/proto/session.h
include/types/connection.h
src/backend.c
src/mux_h1.c
src/mux_h2.c
src/mux_pt.c
src/server.c
src/session.c

index f1e33fa0cd29c13b11b05a81c45f08d0173ae761..2ff8e382d20d1e7a7c6723153fddf1f31215bf7a 100644 (file)
@@ -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;
index af27d0cd10f25f177204a079687e484e9da06841..ab1f8bea815ae26f2521fd2daf8f7fd5d91c1e6a 100644 (file)
@@ -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_*) */
index 5e82bf45034de430eff2a81e20db8a56ef848c55..abe7308e6f88434600ad6e29121e6f7f5d17084f 100644 (file)
@@ -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;
 
                }
index 50afbc20f4689accc82fe3d6d8091426df238586..43b062bbb57703bc098a133e22bab7ed84653bc1 100644 (file)
@@ -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) {
index e44042481364485ca12e078177c75c84095bef08..32e1fc1ab14ef3583b78231746d18334230f57d4 100644 (file)
@@ -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;
index 2086d5fd0a7523c888b08f946f15a9d054afc4f6..6fb9f2f56e6467f96be612045541eb6bd8efdf85 100644 (file)
@@ -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);
 }
 
 /*
index bffc2ee50cf0f1f8eb210aa15050ecbf61f71217..25a918931094f77bdc9c620d41c463043fa972d0 100644 (file)
@@ -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;
index ab49fb6fbdb2fa6327c8b91f237a5abab5e6de32..9b0db46b2390785a0f3e651742b21c6840041ba8 100644 (file)
@@ -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.