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 5932453..6f95575 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1154,14 +1154,25 @@
* 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 @@
/* 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) {