From: Christopher Faulet Date: Wed, 6 Sep 2023 07:09:10 +0000 (+0200) Subject: NUG/MEDIUM: stconn: Always update stream's expiration date after I/O X-Git-Tag: v2.9-dev5~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8073094bf;p=thirdparty%2Fhaproxy.git NUG/MEDIUM: stconn: Always update stream's expiration date after I/O It is a revert of following patches: * d7111e7ac ("MEDIUM: stconn: Don't requeue the stream's task after I/O") * 3479d99d5 ("BUG/MEDIUM: stconn: Update stream expiration date on blocked sends") Because the first one is reverted, the second one is useless and can be reverted too. The issue here is that I/O may be performed without stream wakeup. So if no expiration date was set on the last call to process_stream(), the stream is never rescheduled and no timeout can be detected. This especially happens on TCP streams because fast-forward is enabled very early. Instead of tracking all places where the stream's expiration data must be updated, it is now centralized in sc_notify(), as it was performed before the timeout refactoring. This patch must be backported to 2.8. --- diff --git a/src/applet.c b/src/applet.c index 0264d06b14..a936600a14 100644 --- a/src/applet.c +++ b/src/applet.c @@ -472,8 +472,6 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state) sc_ep_report_send_activity(sc); else { sc_ep_report_blocked_send(sc); - __sc_strm(sc)->task->expire = tick_first(__sc_strm(sc)->task->expire, sc_ep_snd_ex(sc)); - task_queue(__sc_strm(sc)->task); } /* measure the call rate and check for anomalies when too high */ diff --git a/src/stconn.c b/src/stconn.c index 273a1d894e..eaf6d2b383 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1136,6 +1136,20 @@ static void sc_notify(struct stconn *sc) (channel_is_empty(oc) && !oc->to_forward)))))) { task_wakeup(task, TASK_WOKEN_IO); } + else { + /* Update expiration date for the task and requeue it */ + task->expire = (tick_is_expired(task->expire, now_ms) ? 0 : task->expire); + task->expire = tick_first(task->expire, sc_ep_rcv_ex(sc)); + task->expire = tick_first(task->expire, sc_ep_snd_ex(sc)); + task->expire = tick_first(task->expire, sc_ep_rcv_ex(sco)); + task->expire = tick_first(task->expire, sc_ep_snd_ex(sco)); + task->expire = tick_first(task->expire, ic->analyse_exp); + task->expire = tick_first(task->expire, oc->analyse_exp); + task->expire = tick_first(task->expire, __sc_strm(sc)->conn_exp); + + task_queue(task); + } + if (ic->flags & CF_READ_EVENT) sc->flags &= ~SC_FL_RCV_ONCE; } @@ -1695,11 +1709,8 @@ static int sc_conn_send(struct stconn *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)) { + if (sc_state_in(sc->state, SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) sc_ep_report_blocked_send(sc); - s->task->expire = tick_first(s->task->expire, sc_ep_snd_ex(sc)); - task_queue(s->task); - } } return did_send;