mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 06:11:32 +02:00
BUG/MEDIUM: cli: make "show cli sockets" really yield
This command was introduced in 1.8 with commit eceddf722 ("MEDIUM: cli: 'show cli sockets' list the CLI sockets") but its yielding doesn't work. Each time it enters, it restarts from the last bind_conf but enumerates all listening sockets again, thus it loops forever. The risk that it happens in field is low but it easily triggers on port ranges after 400-500 sockets depending on the length of their addresses: global stats socket /tmp/sock1 level admin stats socket 192.168.8.176:30000-31000 level operator $ socat /tmp/sock1 - <<< "show cli sockets" (...) ipv4@192.168.8.176:30426 operator all ipv4@192.168.8.176:30427 operator all ipv4@192.168.8.176:30428 operator all ipv4@192.168.8.176:30000 operator all ipv4@192.168.8.176:30001 operator all ipv4@192.168.8.176:30002 operator all ^C This patch adds the minimally needed restart point for the listener so that it can easily be backported. Some more cleanup is needed though.
This commit is contained in:
parent
4e047e7d0e
commit
241a006d79
29
src/cli.c
29
src/cli.c
@ -1530,11 +1530,11 @@ static int cli_io_handler_show_activity(struct appctx *appctx)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* CLI IO handler for `show cli sockets`.
|
* CLI IO handler for `show cli sockets`.
|
||||||
* Uses ctx.cli.p0 to store the restart pointer.
|
* Uses ctx.cli.p0 to store the bind_conf pointer, and cli.p1 for the listener.
|
||||||
*/
|
*/
|
||||||
static int cli_io_handler_show_cli_sock(struct appctx *appctx)
|
static int cli_io_handler_show_cli_sock(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
struct bind_conf *bind_conf;
|
struct bind_conf *bind_conf = appctx->ctx.cli.p0;
|
||||||
struct conn_stream *cs = appctx->owner;
|
struct conn_stream *cs = appctx->owner;
|
||||||
|
|
||||||
chunk_reset(&trash);
|
chunk_reset(&trash);
|
||||||
@ -1551,23 +1551,16 @@ static int cli_io_handler_show_cli_sock(struct appctx *appctx)
|
|||||||
|
|
||||||
case STAT_ST_LIST:
|
case STAT_ST_LIST:
|
||||||
if (global.cli_fe) {
|
if (global.cli_fe) {
|
||||||
list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
|
if (!bind_conf)
|
||||||
struct listener *l;
|
bind_conf = LIST_ELEM(global.cli_fe->conf.bind.n, typeof(bind_conf), by_fe);
|
||||||
|
|
||||||
/*
|
list_for_each_entry_from(bind_conf, &global.cli_fe->conf.bind, by_fe) {
|
||||||
* get the latest dumped node in appctx->ctx.cli.p0
|
struct listener *l = appctx->ctx.cli.p1;
|
||||||
* if the current node is the first of the list
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (appctx->ctx.cli.p0 &&
|
if (!l)
|
||||||
&bind_conf->by_fe == (&global.cli_fe->conf.bind)->n) {
|
l = LIST_ELEM(bind_conf->listeners.n, typeof(l), by_bind);
|
||||||
/* change the current node to the latest dumped and continue the loop */
|
|
||||||
bind_conf = LIST_ELEM(appctx->ctx.cli.p0, typeof(bind_conf), by_fe);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(l, &bind_conf->listeners, by_bind) {
|
|
||||||
|
|
||||||
|
list_for_each_entry_from(l, &bind_conf->listeners, by_bind) {
|
||||||
char addr[46];
|
char addr[46];
|
||||||
char port[6];
|
char port[6];
|
||||||
|
|
||||||
@ -1605,11 +1598,13 @@ static int cli_io_handler_show_cli_sock(struct appctx *appctx)
|
|||||||
chunk_appendf(&trash, "all\n");
|
chunk_appendf(&trash, "all\n");
|
||||||
|
|
||||||
if (ci_putchk(cs_ic(cs), &trash) == -1) {
|
if (ci_putchk(cs_ic(cs), &trash) == -1) {
|
||||||
|
/* buffer full, we must yield */
|
||||||
|
appctx->ctx.cli.p0 = bind_conf;
|
||||||
|
appctx->ctx.cli.p1 = l;
|
||||||
cs_rx_room_blk(cs);
|
cs_rx_room_blk(cs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appctx->ctx.cli.p0 = &bind_conf->by_fe; /* store the latest list node dumped */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user