From: Olivier Houchard Date: Tue, 21 May 2019 15:43:50 +0000 (+0200) Subject: BUG/MEDIUM: streams: Don't switch from SI_ST_CON to SI_ST_DIS on read0. X-Git-Tag: v2.0-dev4~37 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aacc405c1f2a4173de36ba1a0bf2416d9c958376;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: streams: Don't switch from SI_ST_CON to SI_ST_DIS on read0. When we receive a read0, and we're still in SI_ST_CON state (so on an outgoing conneciton), don't immediately switch to SI_ST_DIS, or, we would never call sess_establish(), and so the analysers will never run. Instead, let sess_establish() handle that case, and switch to SI_ST_DIS if we already have CF_SHUTR on the channel. This should be backported to 1.9. --- diff --git a/src/stream.c b/src/stream.c index f0c7ad21f7..1e88465829 100644 --- a/src/stream.c +++ b/src/stream.c @@ -880,6 +880,11 @@ static int sess_update_st_cer(struct stream *s) * This function handles the transition between the SI_ST_CON state and the * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined. + * Note that it will switch the interface to SI_ST_DIS if we already have + * the CF_SHUTR flag, it means we were able to forward the request, and + * receive the response, before process_stream() had the opportunity to + * make the switch from SI_ST_CON to SI_ST_EST. When that happens, we want + * to go through sess_establish() anyway, to make sure the analysers run. */ static void sess_establish(struct stream *s) { @@ -928,6 +933,9 @@ static void sess_establish(struct stream *s) si_chk_rcv(si); } req->wex = TICK_ETERNITY; + /* If we managed to get the whole response, switch to SI_ST_DIS now. */ + if (rep->flags & CF_SHUTR) + si->state = SI_ST_DIS; } /* Check if the connection request is in such a state that it can be aborted. */ diff --git a/src/stream_interface.c b/src/stream_interface.c index 3b9c707770..22391336e7 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -1486,7 +1486,12 @@ static void stream_int_read0(struct stream_interface *si) si_done_get(si); - si->state = SI_ST_DIS; + /* Don't change the state to SI_ST_DIS yet if we're still + * in SI_ST_CON, otherwise it means sess_establish() hasn't + * been called yet, and so the analysers would not run. + */ + if (si->state == SI_ST_EST) + si->state = SI_ST_DIS; si->exp = TICK_ETERNITY; return; }