DEBUG: mux-h1: Add debug counters to track errors with in/out pending data

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.
This commit is contained in:
Christopher Faulet 2024-10-23 22:51:18 +02:00
parent 1eb31d30fe
commit 7e60928c9c

View File

@ -1020,10 +1020,15 @@ static void h1s_destroy(struct h1s *h1s)
h1c->state = H1_CS_IDLE; h1c->state = H1_CS_IDLE;
h1c->flags |= H1C_F_WAIT_NEXT_REQ; h1c->flags |= H1C_F_WAIT_NEXT_REQ;
h1c->req_count++; 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); TRACE_STATE("set idle mode on h1c, waiting for the next request", H1_EV_H1C_ERR, h1c->conn, h1s);
} }
else { else {
h1_close(h1c); 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); 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 */ 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); b_dequeue(&h1c->buf_wait);
h1_release_buf(h1c, &h1c->ibuf); h1_release_buf(h1c, &h1c->ibuf);
@ -3849,6 +3856,7 @@ static int h1_recv(struct h1c *h1c)
} }
if (h1c->conn->flags & CO_FL_ERROR) { if (h1c->conn->flags & CO_FL_ERROR) {
TRACE_DEVEL("connection error", H1_EV_H1C_RECV, h1c->conn); 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; 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)) { if (h1c->flags & (H1C_F_ERROR|H1C_F_ERR_PENDING)) {
TRACE_DEVEL("leaving on H1C error|err_pending", H1_EV_H1C_SEND, h1c->conn); 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); b_reset(&h1c->obuf);
if (h1c->flags & H1C_F_EOS) if (h1c->flags & H1C_F_EOS)
h1c->flags |= H1C_F_ERROR; h1c->flags |= H1C_F_ERROR;
@ -3916,6 +3925,7 @@ static int h1_send(struct h1c *h1c)
if (conn->flags & CO_FL_ERROR) { if (conn->flags & CO_FL_ERROR) {
/* connection error, nothing to send, clear the buffer to release it */ /* connection error, nothing to send, clear the buffer to release it */
TRACE_DEVEL("connection error", H1_EV_H1C_SEND, h1c->conn); 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; h1c->flags |= H1C_F_ERR_PENDING;
if (h1c->flags & H1C_F_EOS) if (h1c->flags & H1C_F_EOS)
h1c->flags |= H1C_F_ERROR; h1c->flags |= H1C_F_ERROR;
@ -4318,6 +4328,9 @@ struct task *h1_timeout_task(struct task *t, void *context, unsigned int state)
return t; 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 /* We're about to destroy the connection, so make sure nobody attempts
* to steal it from us. * 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) if (conn->flags & CO_FL_SOCK_WR_SH)
return; 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_xprt_shutw(conn);
conn_sock_shutw(conn, !(h1c->flags & H1C_F_SILENT_SHUT)); 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); 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); se_fl_set_error(h1s->sd);
if (sd->iobuf.pipe) { if (sd->iobuf.pipe) {
put_pipe(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); se_fl_set(h1s->sd, SE_FL_ERROR);
h1c->flags = (h1c->flags & ~H1C_F_WANT_FASTFWD) | H1C_F_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(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); 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); h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
} }
se_fl_set_error(h1s->sd); 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) { if (h1s->sd->iobuf.pipe) {
put_pipe(h1s->sd->iobuf.pipe); put_pipe(h1s->sd->iobuf.pipe);
h1s->sd->iobuf.pipe = NULL; h1s->sd->iobuf.pipe = NULL;