From: Olivier Houchard Date: Mon, 28 Jan 2019 14:33:15 +0000 (+0100) Subject: BUG/MEDIUM: servers: Attempt to reuse an unfinished connection on retry. X-Git-Tag: v2.0-dev1~145 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ef5155ba6b7455d3c8c88bf661aa35dd0096003;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: servers: Attempt to reuse an unfinished connection on retry. In connect_server(), if the previous connection failed, but had an alpn, no mux was created, and thus the stream_interface's endpoint would be the connection. In this case, instead of forgetting about it, and overriding the stream_interface's endpoint later, try to reuse the connection, or the connection will still be in the session's connection list, and will reference to a stream that was probably destroyed. This should be backported to 1.9. --- diff --git a/src/backend.c b/src/backend.c index 59324538d6..6f9557563d 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1154,14 +1154,25 @@ int connect_server(struct stream *s) * to use it. */ srv_cs = objt_cs(s->si[1].end); - if (srv_cs) { - old_conn = srv_conn = cs_conn(srv_cs); - if (old_conn && (!old_conn->target || old_conn->target == s->target)) { - old_conn->flags &= ~(CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH); - srv_cs->flags &= ~(CS_FL_ERROR | CS_FL_EOS | CS_FL_REOS); + if (!srv_cs) + srv_conn = objt_conn(s->si[1].end); + else + srv_conn = cs_conn(srv_cs); + + if (srv_conn) { + if (!srv_conn->target || srv_conn->target == s->target) { + srv_conn->flags &= ~(CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH); + if (srv_cs) + srv_cs->flags &= ~(CS_FL_ERROR | CS_FL_EOS | CS_FL_REOS); reuse = 1; + old_conn = srv_conn; + } else { + srv_conn = NULL; + si_release_endpoint(&s->si[1]); } - } else { + } + + if (!old_conn) { struct sess_srv_list *srv_list; list_for_each_entry(srv_list, &s->sess->srv_list, srv_list) { if (srv_list->target == s->target) { @@ -1301,7 +1312,7 @@ int connect_server(struct stream *s) /* We already created a cs earlier when using http_proxy, so * only create a new one if we don't have one already. */ - if (!srv_cs) { + if (!srv_cs && srv_conn->mux) { int avail = srv_conn->mux->avail_streams(srv_conn); if (avail <= 1) {