BUG/MEDIUM: stconn: Forward shutdown on write timeout only if it is forwardable

The commit b9c87f8082 ("BUG/MEDIUM: stconn/stream: Forward shutdown on write
timeout") introduced a regression. In sc_cond_forward_shut(), the write
timeout is considered too early to forward the shutdown. In fact, it is
always considered, even if the shutdown is not forwardable yet. It is of
course unexpected. It is especially an issue when a write timeout is
encountered on server side during the connection establishment. In this
case, if shutdown is forwarded too early on the client side, the connection
is closed before the 503 error sending.

So the write timeout must indeed be considered to forward the shutdown to
the underlying layer, but only if the shutdown is forwardable. Otherwise, we
should do nothing.

This patch should fix the issue #2404. It must be backported as far as 2.2.

(cherry picked from commit 7eb7ae283557d8467403b9db35605861a0870add)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 2b52339ac0fefd9561372e7a777f098dfa00ef1d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit c97832701ec5c606a2c3c2b383617bbbff1efaa5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a334a6f3d7149a1b931bc2c0fe1235568017f339)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1a23a4eaa642ac6ee876f222de037b7f0292a32d)
[cf: Applied on src/stream_interface.c]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 4145fd2..9a83ca3 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -161,15 +161,11 @@
  */
 static inline int si_cond_forward_shutw(struct stream_interface *si)
 {
-	/* Foward the shutdown if an write error occurred on the input channel */
-	if (si_ic(si)->flags & CF_WRITE_TIMEOUT)
-		return 1;
-
 	/* The close must not be forwarded */
 	if (!(si_ic(si)->flags & CF_SHUTR) || !(si->flags & SI_FL_NOHALF))
 		return 0;
 
-	if (!channel_is_empty(si_ic(si))) {
+	if (!channel_is_empty(si_ic(si)) && !(si_ic(si)->flags & CF_WRITE_TIMEOUT)) {
 		/* the close to the write side cannot be forwarded now because
 		 * we should flush outgoing data first. But instruct the output
 		 * channel it should be done ASAP.