From 5e1a9d715ee634a218269d2df10fbfbee4e4c3d2 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Tue, 23 Apr 2019 17:34:22 +0200 Subject: [PATCH] BUG/MEDIUM: stream: Fix the way early aborts on the client side are handled A regression was introduced with the commit c9aecc8ff ("BUG/MEDIUM: stream: Don't request a server connection if a shutw was scheduled"). Among other this, it breaks the CLI when the shutr on the client side is handled with the client data. To depend on the flag CF_SHUTW_NOW to not establish the server connection when an error on the client side is detected is the right way to fix the bug, because this flag may be set without any error on the client side. So instead, we abort the request where the error is handled and only when the backend stream-interface is in the state SI_ST_INI. This way, there is no ambiguity on the reason why the abort accurred. The stream-interface is also switched to the state SI_ST_CLO. This patch must be backported to 1.9. If the commit c9aecc8ff is backported to previous versions, this one MUST also be backported. Otherwise, it MAY be backported to older versions that 1.9 with caution. --- src/stream.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/stream.c b/src/stream.c index e1218e377..cd47b6335 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2140,6 +2140,19 @@ redo: s->flags |= SF_ERR_SRVTO; } sess_set_term_flags(s); + + /* Abort the request if a client error occurred while + * the backend stream-interface is in the SI_ST_INI + * state. It is switched into the SI_ST_CLO state and + * the request channel is erased. */ + if (si_b->state == SI_ST_INI) { + si_b->state = SI_ST_CLO; + channel_abort(req); + if (IS_HTX_STRM(s)) + channel_htx_erase(req, htxbuf(&req->buf)); + else + channel_erase(req); + } } else if (res->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) { /* Report it if the server got an error or a read timeout expired */ @@ -2283,7 +2296,7 @@ redo: * - the CF_AUTO_CONNECT flag is set (active connection) */ if (si_b->state == SI_ST_INI) { - if (!(req->flags & (CF_SHUTW|CF_SHUTW_NOW))) { + if (!(req->flags & CF_SHUTW)) { if ((req->flags & CF_AUTO_CONNECT) || !channel_is_empty(req)) { /* If we have an appctx, there is no connect method, so we * immediately switch to the connected state, otherwise we