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)