]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: connections: Make sure we're unsubscribe before upgrading the mux.
authorOlivier Houchard <ohouchard@haproxy.com>
Wed, 3 Jul 2019 11:08:18 +0000 (13:08 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 3 Jul 2019 11:57:30 +0000 (13:57 +0200)
Just calling conn_force_unsubscribe() from conn_upgrade_mux_fe() is not
enough, as there may be multiple XPRT involved. Instead, require that
any user of conn_upgrade_mux_fe() unsubscribe itself before calling it.
This should fix upgrading a TCP connection to HTX when using SSL.

This should be backported to 2.0.

include/proto/connection.h
src/mux_h1.c
src/proxy.c

index 115e7aaa3bc9a03b993b23d8363bc51d6a246387..88c7e50e52fa37d3edd4e18412e1a219c8df1f43 100644 (file)
@@ -1091,6 +1091,9 @@ static inline int conn_install_mux_be(struct connection *conn, void *ctx, struct
        return conn_install_mux(conn, mux_ops, ctx, prx, sess);
 }
 
+/* Change the mux for the connection.
+ * The caller should make sure he's not subscribed to the underlying XPRT.
+ */
 static inline int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct buffer *buf,
                                      struct ist mux_proto, int mode)
 {
@@ -1118,7 +1121,6 @@ static inline int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct
        old_mux_ctx = conn->ctx;
        conn->mux = new_mux;
        conn->ctx = ctx;
-       conn_force_unsubscribe(conn);
        if (new_mux->init(conn, bind_conf->frontend, conn->owner, buf) == -1) {
                /* The mux upgrade failed, so restore the old mux */
                conn->ctx = old_mux_ctx;
index 37cc8252dd2a6a7a7e41e96392bcaf9946617f55..e0880e5e8d8dabfad167bddaa05bae2f386c6a78 100644 (file)
@@ -465,6 +465,10 @@ static void h1_release(struct h1c *h1c)
 
                if (conn && h1c->flags & H1C_F_UPG_H2C) {
                        h1c->flags &= ~H1C_F_UPG_H2C;
+                       /* Make sure we're no longer subscribed to anything */
+                       if (h1c->wait_event.events)
+                               conn->xprt->unsubscribe(conn, conn->xprt_ctx,
+                                   h1c->wait_event.events, &h1c->wait_event);
                        if (conn_upgrade_mux_fe(conn, NULL, &h1c->ibuf, ist("h2"), PROTO_MODE_HTX) != -1) {
                                /* connection successfully upgraded to H2, this
                                 * mux was already released */
index 731f5e2a60a4766579c90391f15ceb8f82e88a34..329626821da30b62b9480c1086b8e951cf9df1f2 100644 (file)
@@ -1470,6 +1470,13 @@ int stream_set_backend(struct stream *s, struct proxy *be)
 
                        if (conn && cs) {
                                si_rx_endp_more(&s->si[0]);
+                               /* Make sure we're unsubscribed, the the new
+                                * mux will probably want to subscribe to
+                                * the underlying XPRT
+                                */
+                               if (s->si[0].wait_event.events)
+                                       conn->mux->unsubscribe(cs, s->si[0].wait_event.events,
+                                           &s->si[0].wait_event);
                                if (conn_upgrade_mux_fe(conn, cs, &s->req.buf, ist(""), PROTO_MODE_HTX)  == -1)
                                        return 0;
                                s->flags |= SF_HTX;