From bddf7fc4179896bb60c35b28b9cbd41599889f2a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 19 Dec 2018 17:17:10 +0100 Subject: [PATCH] MEDIUM: stream-int: always consider all CS errors on the send side We still have an issue with asynchronous errors, which is that while they don't truncate reads anymore, they might be missed during a send() attempt. This can happen for example when processing a request followed by undesired data for which the stream doesn't try to receive, while the send side experiences an error (transfer aborted by the client). In this case we definitely want all send() attempts to fail as soon as the error was reported, even if it's only pending. This way we leave an opportunity to the stream interface to try to receive the last data pending in the buffer but it cannot send anymore and knows that there is an error when trying to do so. --- src/stream_interface.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/stream_interface.c b/src/stream_interface.c index d8fd6bdcc..05306cf5a 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -615,8 +615,10 @@ int si_cs_send(struct conn_stream *cs) if (si->wait_event.events & SUB_RETRY_SEND) return 0; - if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) + if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) { + si->flags |= SI_FL_ERR; return 1; + } /* we might have been called just after an asynchronous shutw */ if (conn->flags & CO_FL_SOCK_WR_SH || oc->flags & CF_SHUTW) @@ -634,8 +636,10 @@ int si_cs_send(struct conn_stream *cs) oc->pipe = NULL; } - if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) + if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) { + si->flags |= SI_FL_ERR; return 1; + } if (oc->pipe) goto end; @@ -689,8 +693,10 @@ int si_cs_send(struct conn_stream *cs) */ } - if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) + if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) { + si->flags |= SI_FL_ERR; return 1; + } } end: @@ -838,7 +844,7 @@ void si_update_both(struct stream_interface *si_f, struct stream_interface *si_b (si_b->state == SI_ST_EST || si_b->state == SI_ST_CON) && !(req->flags & CF_SHUTW) && /* Write not closed */ !channel_is_empty(req) && - !(cs->flags & CS_FL_ERROR) && + !(cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) && !(cs->conn->flags & CO_FL_ERROR)) { if (si_cs_send(cs)) si_rx_room_rdy(si_f); @@ -1023,7 +1029,7 @@ static void stream_int_chk_snd_conn(struct stream_interface *si) if (!(si->wait_event.events & SUB_RETRY_SEND) && !channel_is_empty(si_oc(si))) si_cs_send(cs); - if (cs->flags & CS_FL_ERROR || cs->conn->flags & CO_FL_ERROR) { + if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING) || cs->conn->flags & CO_FL_ERROR) { /* Write error on the file descriptor */ si->flags |= SI_FL_ERR; goto out_wakeup;