]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
NUG/MEDIUM: stconn: Always update stream's expiration date after I/O
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 Sep 2023 07:09:10 +0000 (09:09 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 Sep 2023 07:29:27 +0000 (09:29 +0200)
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.

src/applet.c
src/stconn.c

index 0264d06b14349d120205bb7e5026b409aa8a354a..a936600a148e3bb30329eafea93de02e7d7baea7 100644 (file)
@@ -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 */
index 273a1d894e36905ecbfa3ab2b94b53d07af36889..eaf6d2b383553ca5e3e97b7e5f5303ab836c6325 100644 (file)
@@ -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;