From: Christopher Faulet Date: Wed, 15 Nov 2023 16:33:06 +0000 (+0100) Subject: BUG/MEDIUM: stconn: Update fsb date on partial sends X-Git-Tag: v2.9-dev10~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b68c579eda648090f14e977ce84ef816a4b4200d;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stconn: Update fsb date on partial sends The first-send-blocked date was originally designed to save the date of the first send of a series where some data remain blocked. It was relaxed recently (3083fd90e "BUG/MEDIUM: stconn: Report a send activity everytime data were sent") to save the date of the first full blocked send. However, it is not accurrate. When all data are sent, the fsb value must be reset to TICK_ETERNITY. When nothing is sent and if it is not already set, it must be set. But when data are partially sent, the value must be updated and not reset. Otherwise the write timeout may be ignored because fsb date is never set. So, changes brought by the patch above are reverted and sc_ep_report_blocked_send() was changed to know if some data were sent or not. This way we are able to update fsb value. l This patch must be backported to 2.8. --- diff --git a/include/haproxy/stconn.h b/include/haproxy/stconn.h index 4e8722e4a7..fa2a6726bd 100644 --- a/include/haproxy/stconn.h +++ b/include/haproxy/stconn.h @@ -182,11 +182,11 @@ static forceinline void sc_ep_report_read_activity(struct stconn *sc) } /* Report a send blocked. This function sets to now_ms if it was not - * already set + * already set or if something was sent (to renew ). */ -static forceinline void sc_ep_report_blocked_send(struct stconn *sc) +static forceinline void sc_ep_report_blocked_send(struct stconn *sc, int did_send) { - if (!tick_isset(sc->sedesc->fsb)) + if (did_send || !tick_isset(sc->sedesc->fsb)) sc->sedesc->fsb = now_ms; } @@ -529,10 +529,12 @@ static inline void se_done_ff(struct sedesc *se) BUG_ON(!mux->done_fastfwd); sent = mux->done_fastfwd(se->sc); - if (sent > 0) - sc_ep_report_send_activity(se->sc); - else if (to_send > 0) /* implies sent == 0 */ - sc_ep_report_blocked_send(se->sc); + if (to_send) { + if (sent == to_send) + sc_ep_report_send_activity(se->sc); + else + sc_ep_report_blocked_send(se->sc, sent != 0); + } } } diff --git a/src/applet.c b/src/applet.c index 93178ec14a..e7bf088775 100644 --- a/src/applet.c +++ b/src/applet.c @@ -406,6 +406,7 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state) struct stconn *sc, *sco; unsigned int rate; size_t count; + int did_send = 0; TRACE_ENTER(APPLET_EV_PROCESS, app); @@ -462,11 +463,11 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state) if (sco->room_needed < 0 || channel_recv_max(sc_oc(sc)) >= sco->room_needed) sc_have_room(sco); sc_ep_report_send_activity(sc); + did_send = 1; } else { if (!sco->room_needed) sc_have_room(sco); - sc_ep_report_blocked_send(sc); } if (sc_ic(sc)->flags & CF_READ_EVENT) @@ -476,6 +477,11 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state) sc_ep_set(sc, SE_FL_EOS|SE_FL_ERROR); } + if (!co_data(sc_oc(sc))) + sc_ep_report_send_activity(sc); + else + sc_ep_report_blocked_send(sc, did_send); + /* measure the call rate and check for anomalies when too high */ if (((b_size(sc_ib(sc)) && sc->flags & SC_FL_NEED_BUFF) || // asks for a buffer which is present (b_size(sc_ib(sc)) && !b_data(sc_ib(sc)) && sc->flags & SC_FL_NEED_ROOM) || // asks for room in an empty buffer diff --git a/src/stconn.c b/src/stconn.c index c768bc8ff3..f8eb4ae03d 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1690,11 +1690,6 @@ static int sc_conn_send(struct stconn *sc) oc->flags |= CF_WRITE_EVENT | CF_WROTE_DATA; if (sc->state == SC_ST_CON) sc->state = SC_ST_RDY; - sc_ep_report_send_activity(sc); - } - else { - if (sc_state_in(sc->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) - sc_ep_report_blocked_send(sc); } if (!sco->room_needed || (did_send && (sco->room_needed < 0 || channel_recv_max(sc_oc(sc)) >= sco->room_needed))) @@ -1718,10 +1713,13 @@ static int sc_conn_send(struct stconn *sc) sc_have_room(sco); did_send = 1; } + sc_ep_report_send_activity(sc); } else { /* We couldn't send all of our data, let the mux know we'd like to send more */ conn->mux->subscribe(sc, SUB_RETRY_SEND, &sc->wait_event); + if (sc_state_in(sc->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) + sc_ep_report_blocked_send(sc, did_send); } return did_send;