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
int (*unsubscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Unsubscribe <es> 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
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 <es> to events, such as "being able to send" */
int (*unsubscribe)(struct conn_stream *cs, int event_type, struct wait_event *es); /* Unsubscribe <es> from events */
int (*avail_streams)(struct connection *conn); /* Returns the number of streams still available for a connection */
const void *xprt_ctx = NULL;
uint32_t conn_flags = 0;
int is_back = 0;
+ int suspicious = 0;
fdt = fdtab[fd];
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");
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) {
#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);
}
/* 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;
struct buffer *hmbuf, *tmbuf;
if (!fconn)
- return;
+ return 0;
list_for_each_entry(fstrm, &fconn->send_list, send_list)
send_cnt++;
}
}
}
+ return 0;
}
/* Migrate the the connection to the current thread.
}
/* 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;
}
}
}
+ return 0;
}
}
/* 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;
struct buffer *hmbuf, *tmbuf;
if (!h2c)
- return;
+ return 0;
list_for_each_entry(h2s, &h2c->fctl_list, list)
fctl_cnt++;
}
}
}
+ return 0;
}
/* Migrate the the connection to the current thread.
/* "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);
}
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)