]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEBUG: mux-h1: Add debug counters to track errors with in/out pending data
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 23 Oct 2024 20:51:18 +0000 (22:51 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 24 Oct 2024 06:18:55 +0000 (08:18 +0200)
Debug counters were added on all connection error when pending data remain
blocked in the input or ouput buffers. The same is performed when the H1C is
released, when the connection is closed and when a timeout is reached. Idea
is to be able to count all cases where data are lost, especially the
outgoing ones.

src/mux_h1.c

index 794740a79387cd5d55dc9766c7c216f602951861..ccdf3cdfa2194270a6d2f993e3d8d4302406afcf 100644 (file)
@@ -1020,10 +1020,15 @@ static void h1s_destroy(struct h1s *h1s)
                        h1c->state = H1_CS_IDLE;
                        h1c->flags |= H1C_F_WAIT_NEXT_REQ;
                        h1c->req_count++;
+
+                       COUNT_IF(!(h1c->flags & H1C_F_IS_BACK) && b_data(&h1c->obuf), "front H1C switched in IDLE state with pending outgoing data");
+                       COUNT_IF((h1c->flags & H1C_F_IS_BACK) && b_data(&h1c->obuf), "back H1C switched in IDLE state with pending outgoing data");
                        TRACE_STATE("set idle mode on h1c, waiting for the next request", H1_EV_H1C_ERR, h1c->conn, h1s);
                }
                else {
                        h1_close(h1c);
+                       COUNT_IF(!(h1c->flags & H1C_F_IS_BACK) && b_data(&h1c->obuf), "front H1C swiched in CLOSED state with pending outgoing data");
+                       COUNT_IF((h1c->flags & H1C_F_IS_BACK) && b_data(&h1c->obuf), "back H1C switch in CLOSED state with pending outgoing data");
                        TRACE_STATE("close h1c", H1_EV_H1S_END, h1c->conn, h1s);
                }
 
@@ -1355,6 +1360,8 @@ static void h1_release(struct h1c *h1c)
                sess_log(conn->owner); /* Log if the upgrade failed */
        }
 
+       COUNT_IF(b_data(&h1c->ibuf), "H1C released with pending input data");
+       COUNT_IF(b_data(&h1c->obuf), "H1C released with pending output data");
 
        b_dequeue(&h1c->buf_wait);
        h1_release_buf(h1c, &h1c->ibuf);
@@ -3849,6 +3856,7 @@ static int h1_recv(struct h1c *h1c)
        }
        if (h1c->conn->flags & CO_FL_ERROR) {
                TRACE_DEVEL("connection error", H1_EV_H1C_RECV, h1c->conn);
+               COUNT_IF(b_data(&h1c->obuf), "connection error (recv) with pending output data");
                h1c->flags |= H1C_F_ERROR;
        }
 
@@ -3887,6 +3895,7 @@ static int h1_send(struct h1c *h1c)
 
        if (h1c->flags & (H1C_F_ERROR|H1C_F_ERR_PENDING)) {
                TRACE_DEVEL("leaving on H1C error|err_pending", H1_EV_H1C_SEND, h1c->conn);
+               COUNT_IF(b_data(&h1c->obuf), "connection error (send) with pending output data");
                b_reset(&h1c->obuf);
                if (h1c->flags & H1C_F_EOS)
                        h1c->flags |= H1C_F_ERROR;
@@ -3916,6 +3925,7 @@ static int h1_send(struct h1c *h1c)
        if (conn->flags & CO_FL_ERROR) {
                /* connection error, nothing to send, clear the buffer to release it */
                TRACE_DEVEL("connection error", H1_EV_H1C_SEND, h1c->conn);
+               COUNT_IF(b_data(&h1c->obuf), "connection error (send) with pending output data");
                h1c->flags |= H1C_F_ERR_PENDING;
                if (h1c->flags & H1C_F_EOS)
                        h1c->flags |= H1C_F_ERROR;
@@ -4318,6 +4328,9 @@ struct task *h1_timeout_task(struct task *t, void *context, unsigned int state)
                        return t;
                }
 
+               COUNT_IF(b_data(&h1c->ibuf), "H1C timed out with pending input data");
+               COUNT_IF(b_data(&h1c->obuf), "H1C timed out with pending output data");
+
                /* We're about to destroy the connection, so make sure nobody attempts
                 * to steal it from us.
                 */
@@ -4480,6 +4493,9 @@ static void h1_shutw_conn(struct connection *conn)
        if (conn->flags & CO_FL_SOCK_WR_SH)
                return;
 
+       COUNT_IF(b_data(&h1c->ibuf), "close connection with pending input data");
+       COUNT_IF(b_data(&h1c->obuf), "close connection with pending output data");
+
        conn_xprt_shutw(conn);
        conn_sock_shutw(conn, !(h1c->flags & H1C_F_SILENT_SHUT));
 
@@ -4893,6 +4909,7 @@ static size_t h1_done_ff(struct stconn *sc)
                         */
                        h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
                }
+               COUNT_IF(b_data(&h1c->obuf) || sd->iobuf.pipe->data, "connection error (done_ff) with pending output data");
                se_fl_set_error(h1s->sd);
                if (sd->iobuf.pipe) {
                        put_pipe(sd->iobuf.pipe);
@@ -5072,6 +5089,7 @@ static int h1_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags)
                se_fl_set(h1s->sd, SE_FL_ERROR);
                h1c->flags = (h1c->flags & ~H1C_F_WANT_FASTFWD) | H1C_F_ERROR;
                COUNT_IF(h1m->state < H1_MSG_DONE, "H1C ERROR before the end of the message");
+               COUNT_IF(b_data(&h1c->obuf) || h1s->sd->iobuf.pipe->data, "connection error (fastfwd) with pending output data");
                TRACE_DEVEL("connection error", H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s);
        }
 
@@ -5153,6 +5171,7 @@ static int h1_resume_fastfwd(struct stconn *sc, unsigned int flags)
                        h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
                }
                se_fl_set_error(h1s->sd);
+               COUNT_IF(b_data(&h1c->obuf) || h1s->sd->iobuf.pipe->data, "connection error (resume_ff) with pending output data");
                if (h1s->sd->iobuf.pipe) {
                        put_pipe(h1s->sd->iobuf.pipe);
                        h1s->sd->iobuf.pipe = NULL;