From 7a3367cca0d1fddcfe6d13da31d0607dbd24e29e Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 9 May 2019 11:46:52 +0200 Subject: [PATCH] BUG/MINOR: stream: Attach the read side on the response as soon as possible A backend stream-interface attached to a reused connection remains in the state SI_ST_CONN until some data are sent to validate the connection. But when the url_param algorithm is used to balance connections, no data are sent while the connection is not established. So it is a chicken and egg situation. To solve the problem, if no error is detected and when the request channel is waiting for the connect(), we mark the read side as attached on the response channel as soon as possible and we wake the request channel up once. This happens in 2 places. The first one is right after the connect(), when the stream-interface is still in state SI_ST_CON, in the function sess_update_st_con_tcp(). The second one is when an applet is used instead of a real connection to a server, in the function sess_prepare_conn_req(). In fact, it is done when the backend stream-interface is set to the state SI_ST_EST. This patch must be backported to 1.9. --- src/stream.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/stream.c b/src/stream.c index 8c2ea5561..58e1cc11b 100644 --- a/src/stream.c +++ b/src/stream.c @@ -711,6 +711,16 @@ static int sess_update_st_con_tcp(struct stream *s) return 1; } + /* If the request channel is waiting for the connect(), we mark the read + * side as attached on the response channel and we wake up it once. So + * it will have a chance to forward data now. + */ + if (req->flags & CF_WAKE_CONNECT) { + rep->flags |= CF_READ_ATTACHED; + req->flags |= CF_WAKE_ONCE; + req->flags &= ~CF_WAKE_CONNECT; + } + /* we need to wait a bit more if there was no activity either */ if (!(req->flags & CF_WRITE_ACTIVITY)) return 1; @@ -900,10 +910,6 @@ static void sess_establish(struct stream *s) si_rx_endp_more(si); rep->flags |= CF_READ_ATTACHED; /* producer is now attached */ - if (req->flags & CF_WAKE_CONNECT) { - req->flags |= CF_WAKE_ONCE; - req->flags &= ~CF_WAKE_CONNECT; - } if (objt_cs(si->end)) { /* real connections have timeouts */ req->wto = s->be->timeout.server; @@ -1181,6 +1187,17 @@ static void sess_prepare_conn_req(struct stream *s) return; } + /* For applets, there is no connection establishment, but if the + * request channel is waiting for it, we mark the read side as + * attached on the response channel and we wake up it once. So + * it will have a chance to forward data now. + */ + if (s->req.flags & CF_WAKE_CONNECT) { + s->res.flags |= CF_READ_ATTACHED; + s->req.flags |= CF_WAKE_ONCE; + s->req.flags &= ~CF_WAKE_CONNECT; + } + if (tv_iszero(&s->logs.tv_request)) s->logs.tv_request = now; s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);