]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stconn: Update fsb date on partial sends
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 15 Nov 2023 16:33:06 +0000 (17:33 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 17 Nov 2023 11:13:00 +0000 (12:13 +0100)
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.

include/haproxy/stconn.h
src/applet.c
src/stconn.c

index 4e8722e4a71fcdc0d97c5b63eb38b1f889f463eb..fa2a6726bd3cff96034d85693b3df11797914736 100644 (file)
@@ -182,11 +182,11 @@ static forceinline void sc_ep_report_read_activity(struct stconn *sc)
 }
 
 /* Report a send blocked. This function sets <fsb> to now_ms if it was not
- * already set
+ * already set or if something was sent (to renew <fsb>).
  */
-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);
+               }
        }
 }
 
index 93178ec14aa2fa4e36cebaec3bbd07b029ad584b..e7bf08877505123fa028359437c2850250c0b5e9 100644 (file)
@@ -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
index c768bc8ff31196ab1bf4619d9cc69c957c536042..f8eb4ae03d03c1efe99890a627b701570a8ceaad 100644 (file)
@@ -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;