From 8050efeacb554f798a49db5ef213c8f673e5596e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 21 Jan 2021 08:26:06 +0100 Subject: [PATCH] MINOR: cli: give the show_fd helpers the ability to report a suspicious entry Now the show_fd helpers at the transport and mux levels return an integer which indicates whether or not the inspected entry looks suspicious. When an entry is reported as suspicious, "show fd" will suffix it with an exclamation mark ('!') in the dump, that is supposed to help detecting them. For now, helpers were adjusted to adapt to the new API but none of them reports any suspicious entry yet. --- doc/management.txt | 5 ++++- include/haproxy/connection-t.h | 4 ++-- src/cli.c | 7 ++++--- src/mux_fcgi.c | 5 +++-- src/mux_h1.c | 3 ++- src/mux_h2.c | 5 +++-- src/ssl_sock.c | 5 +++-- 7 files changed, 21 insertions(+), 13 deletions(-) diff --git a/doc/management.txt b/doc/management.txt index 2600478fd..f77ed4c1b 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -2126,7 +2126,10 @@ show fd [] listener's state and its frontend are reported. There is no point in using this command without a good knowledge of the internals. It's worth noting that the output format may evolve over time so this output must not be parsed - by tools designed to be durable. + by tools designed to be durable. Some internal structure states may look + suspicious to the function listing them, in this case the output line will be + suffixed with an exclamation mark ('!'). This may help find a starting point + when trying to diagnose an incident. show info [typed|json] [desc] Dump info about haproxy status on current process. If "typed" is passed as an diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 7dd3d15d9..62bb81441 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -381,7 +381,7 @@ struct xprt_ops { int (*unsubscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Unsubscribe from events */ int (*remove_xprt)(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx); /* Remove an xprt from the connection, used by temporary xprt such as the handshake one */ int (*add_xprt)(struct connection *conn, void *xprt_ctx, void *toadd_ctx, const struct xprt_ops *toadd_ops, void **oldxprt_ctx, const struct xprt_ops **oldxprt_ops); /* Add a new XPRT as the new xprt, and return the old one */ - void (*show_fd)(struct buffer *, const struct connection *, const void *ctx); /* append some data about xprt for "show fd" */ + int (*show_fd)(struct buffer *, const struct connection *, const void *ctx); /* append some data about xprt for "show fd"; returns non-zero if suspicious */ }; /* mux_ops describes the mux operations, which are to be performed at the @@ -404,7 +404,7 @@ struct mux_ops { struct conn_stream *(*attach)(struct connection *, struct session *sess); /* Create and attach a conn_stream to an outgoing connection */ const struct conn_stream *(*get_first_cs)(const struct connection *); /* retrieves any valid conn_stream from this connection */ void (*detach)(struct conn_stream *); /* Detach a conn_stream from an outgoing connection, when the request is done */ - void (*show_fd)(struct buffer *, struct connection *); /* append some data about connection into chunk for "show fd" */ + int (*show_fd)(struct buffer *, struct connection *); /* append some data about connection into chunk for "show fd"; returns non-zero if suspicious */ int (*subscribe)(struct conn_stream *cs, int event_type, struct wait_event *es); /* Subscribe to events, such as "being able to send" */ int (*unsubscribe)(struct conn_stream *cs, int event_type, struct wait_event *es); /* Unsubscribe from events */ int (*avail_streams)(struct connection *conn); /* Returns the number of streams still available for a connection */ diff --git a/src/cli.c b/src/cli.c index 060372988..ab5fe9a15 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1037,6 +1037,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) const void *xprt_ctx = NULL; uint32_t conn_flags = 0; int is_back = 0; + int suspicious = 0; fdt = fdtab[fd]; @@ -1100,7 +1101,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) if (mux) { chunk_appendf(&trash, " mux=%s ctx=%p", mux->name, ctx); if (mux->show_fd) - mux->show_fd(&trash, fdt.owner); + suspicious |= mux->show_fd(&trash, fdt.owner); } else chunk_appendf(&trash, " nomux"); @@ -1110,7 +1111,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) if (xprt_ctx || xprt->show_fd) chunk_appendf(&trash, " xprt_ctx=%p", xprt_ctx); if (xprt->show_fd) - xprt->show_fd(&trash, conn, xprt_ctx); + suspicious |= xprt->show_fd(&trash, conn, xprt_ctx); } } else if (fdt.iocb == sock_accept_iocb) { @@ -1124,7 +1125,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) #ifdef DEBUG_FD chunk_appendf(&trash, " evcnt=%u", fdtab[fd].event_count); #endif - chunk_appendf(&trash, "\n"); + chunk_appendf(&trash, "%s\n", suspicious ? " !" : ""); if (ci_putchk(si_ic(si), &trash) == -1) { si_rx_room_blk(si); diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c index 4e2f0cced..765cff3b8 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -4053,7 +4053,7 @@ static size_t fcgi_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t co } /* for debugging with CLI's "show fd" command */ -static void fcgi_show_fd(struct buffer *msg, struct connection *conn) +static int fcgi_show_fd(struct buffer *msg, struct connection *conn) { struct fcgi_conn *fconn = conn->ctx; struct fcgi_strm *fstrm = NULL; @@ -4064,7 +4064,7 @@ static void fcgi_show_fd(struct buffer *msg, struct connection *conn) struct buffer *hmbuf, *tmbuf; if (!fconn) - return; + return 0; list_for_each_entry(fstrm, &fconn->send_list, send_list) send_cnt++; @@ -4116,6 +4116,7 @@ static void fcgi_show_fd(struct buffer *msg, struct connection *conn) } } } + return 0; } /* Migrate the the connection to the current thread. diff --git a/src/mux_h1.c b/src/mux_h1.c index 4a4b5edc4..ae50a5ef9 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -3141,7 +3141,7 @@ static int h1_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *outp } /* for debugging with CLI's "show fd" command */ -static void h1_show_fd(struct buffer *msg, struct connection *conn) +static int h1_show_fd(struct buffer *msg, struct connection *conn) { struct h1c *h1c = conn->ctx; struct h1s *h1s = h1c->h1s; @@ -3181,6 +3181,7 @@ static void h1_show_fd(struct buffer *msg, struct connection *conn) } } } + return 0; } diff --git a/src/mux_h2.c b/src/mux_h2.c index 0a4a62af5..2fbf19675 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -6192,7 +6192,7 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun } /* for debugging with CLI's "show fd" command */ -static void h2_show_fd(struct buffer *msg, struct connection *conn) +static int h2_show_fd(struct buffer *msg, struct connection *conn) { struct h2c *h2c = conn->ctx; struct h2s *h2s = NULL; @@ -6204,7 +6204,7 @@ static void h2_show_fd(struct buffer *msg, struct connection *conn) struct buffer *hmbuf, *tmbuf; if (!h2c) - return; + return 0; list_for_each_entry(h2s, &h2c->fctl_list, list) fctl_cnt++; @@ -6262,6 +6262,7 @@ static void h2_show_fd(struct buffer *msg, struct connection *conn) } } } + return 0; } /* Migrate the the connection to the current thread. diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 483662ec2..ca8dcc63c 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -6354,12 +6354,12 @@ static int ssl_check_async_engine_count(void) { /* "show fd" helper to dump ssl internals. Warning: the output buffer is often * the common trash! */ -static void ssl_sock_show_fd(struct buffer *buf, const struct connection *conn, const void *ctx) +static int ssl_sock_show_fd(struct buffer *buf, const struct connection *conn, const void *ctx) { const struct ssl_sock_ctx *sctx = ctx; if (!sctx) - return; + return 0; if (sctx->conn != conn) chunk_appendf(&trash, " xctx.conn=%p(BOGUS!)", sctx->conn); @@ -6383,6 +6383,7 @@ static void ssl_sock_show_fd(struct buffer *buf, const struct connection *conn, } chunk_appendf(&trash, " .sent_early=%d", sctx->sent_early_data); chunk_appendf(&trash, " .early_in=%d", (int)sctx->early_buf.data); + return 0; } #if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)