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.
This commit is contained in:
Willy Tarreau 2018-12-19 17:17:10 +01:00
parent 9117780bfd
commit bddf7fc417

View File

@ -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;