0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

CLI: Fix for long-lived sessions during high loads

When there is a continuos stream of CLI commands, cli_get_command()
always returns 1 (there is a new command). Anyway, the socket receive
buffer was reset only when there was no command at all, leading to a
strange behavior: after a while, the CLI receive buffer came to its end,
then read() was called with zero size buffer, it returned 0 which was
interpreted as EOF.

The patch fixes that by resetting the buffer position after each command
and moving remaining data at the beginning of buffer.

Thanks to Maria Matejka for examining the bug and for the original bugfix.
This commit is contained in:
Ondrej Zajicek 2022-12-10 17:32:42 +01:00 committed by Igor Putovny
parent 9aa5a3d958
commit c9ff0627a7
2 changed files with 12 additions and 7 deletions

View File

@ -29,7 +29,7 @@ typedef struct cli {
node n; /* Node in list of all log hooks */ node n; /* Node in list of all log hooks */
pool *pool; pool *pool;
void *priv; /* Private to sysdep layer */ void *priv; /* Private to sysdep layer */
byte *rx_buf, *rx_pos, *rx_aux; /* sysdep */ byte *rx_buf, *rx_pos; /* sysdep */
struct cli_out *tx_buf, *tx_pos, *tx_write; struct cli_out *tx_buf, *tx_pos, *tx_write;
event *event; event *event;
void (*cont)(struct cli *c); void (*cont)(struct cli *c);

View File

@ -441,7 +441,7 @@ int
cli_get_command(cli *c) cli_get_command(cli *c)
{ {
sock *s = c->priv; sock *s = c->priv;
byte *t = c->rx_aux ? : s->rbuf; byte *t = s->rbuf;
byte *tend = s->rpos; byte *tend = s->rpos;
byte *d = c->rx_pos; byte *d = c->rx_pos;
byte *dend = c->rx_buf + CLI_RX_BUF_SIZE - 2; byte *dend = c->rx_buf + CLI_RX_BUF_SIZE - 2;
@ -452,16 +452,22 @@ cli_get_command(cli *c)
t++; t++;
else if (*t == '\n') else if (*t == '\n')
{ {
t++;
c->rx_pos = c->rx_buf;
c->rx_aux = t;
*d = 0; *d = 0;
t++;
/* Move remaining data and reset pointers */
uint rest = (t < tend) ? (tend - t) : 0;
memmove(s->rbuf, t, rest);
s->rpos = s->rbuf + rest;
c->rx_pos = c->rx_buf;
return (d < dend) ? 1 : -1; return (d < dend) ? 1 : -1;
} }
else if (d < dend) else if (d < dend)
*d++ = *t++; *d++ = *t++;
} }
c->rx_aux = s->rpos = s->rbuf;
s->rpos = s->rbuf;
c->rx_pos = d; c->rx_pos = d;
return 0; return 0;
} }
@ -508,7 +514,6 @@ cli_connect(sock *s, uint size UNUSED)
s->pool = c->pool; /* We need to have all the socket buffers allocated in the cli pool */ s->pool = c->pool; /* We need to have all the socket buffers allocated in the cli pool */
s->fast_rx = 1; s->fast_rx = 1;
c->rx_pos = c->rx_buf; c->rx_pos = c->rx_buf;
c->rx_aux = NULL;
rmove(s, c->pool); rmove(s, c->pool);
return 1; return 1;
} }