From 5cd62171858d38e805604e63746da44e09e94e03 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Fri, 4 Jan 2019 15:52:26 +0100 Subject: [PATCH] BUG/MEDIUM: server: Defer the mux init until after xprt has been initialized. In connect_server(), if we're using a new connection, and we have to initialize the mux right away, only do it so after si_connect() has been called. si_connect() is responsible for initializing the xprt, and the mux initialization may depend on the xprt being usable, as it may try to receive data. Otherwise, the connection will be flagged as having an error, and we will have to try to connect a second time. This should be backported to 1.9. --- src/backend.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/backend.c b/src/backend.c index c92e76172..3c0ea8b4e 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1120,6 +1120,7 @@ int connect_server(struct stream *s) struct server *srv; int reuse = 0; int reuse_orphan = 0; + int init_mux = 0; int err; @@ -1346,15 +1347,7 @@ int connect_server(struct stream *s) conn_free(srv_conn); return SF_ERR_RESOURCE; } - if (conn_install_mux_be(srv_conn, srv_cs, s->sess) < 0) - return SF_ERR_INTERNAL; - /* If we're doing http-reuse always, and the connection - * is an http2 connection, add it to the available list, - * so that others can use it right away. - */ - if (srv && ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS) && - srv_conn->mux->avail_streams(srv_conn) > 0) - LIST_ADD(&srv->idle_conns[tid], &srv_conn->list); + init_mux = 1; } #if defined(USE_OPENSSL) && defined(TLSEXT_TYPE_application_layer_protocol_negotiation) else { @@ -1411,6 +1404,23 @@ int connect_server(struct stream *s) } err = si_connect(&s->si[1], srv_conn); + /* We have to defer the mux initialization until after si_connect() + * has been called, as we need the xprt to have been properly + * initialized, or any attempt to recv during the mux init may + * fail, and flag the connection as CO_FL_ERROR. + */ + if (init_mux) { + if (conn_install_mux_be(srv_conn, srv_cs, s->sess) < 0) + return SF_ERR_INTERNAL; + /* If we're doing http-reuse always, and the connection + * is an http2 connection, add it to the available list, + * so that others can use it right away. + */ + if (srv && ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS) && + srv_conn->mux->avail_streams(srv_conn) > 0) + LIST_ADD(&srv->idle_conns[tid], &srv_conn->list); + } + #ifdef USE_OPENSSL if (!reuse && cli_conn && srv &&