]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
CLI: Fix for long-lived sessions during high loads
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 10 Dec 2022 16:32:42 +0000 (17:32 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 10 Dec 2022 16:32:42 +0000 (17:32 +0100)
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.

nest/cli.h
sysdep/unix/main.c

index 8a3294c52224d5e618219ddd5d77b6f0e7831902..3596e37ca777d504c9784bbd1683d84f59ef23b8 100644 (file)
@@ -29,7 +29,7 @@ typedef struct cli {
   node n;                              /* Node in list of all log hooks */
   pool *pool;
   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;
   event *event;
   void (*cont)(struct cli *c);
index 18fd4e4498716d362b09ce34b86a47f1aceb1c8d..627d7a4a80158fb9c90f7a801c1abe035a34ce3c 100644 (file)
@@ -441,7 +441,7 @@ int
 cli_get_command(cli *c)
 {
   sock *s = c->priv;
-  byte *t = c->rx_aux ? : s->rbuf;
+  byte *t = s->rbuf;
   byte *tend = s->rpos;
   byte *d = c->rx_pos;
   byte *dend = c->rx_buf + CLI_RX_BUF_SIZE - 2;
@@ -452,16 +452,22 @@ cli_get_command(cli *c)
        t++;
       else if (*t == '\n')
        {
+         *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;
-         c->rx_aux = t;
-         *d = 0;
+
          return (d < dend) ? 1 : -1;
        }
       else if (d < dend)
        *d++ = *t++;
     }
-  c->rx_aux = s->rpos = s->rbuf;
+
+  s->rpos = s->rbuf;
   c->rx_pos = d;
   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->fast_rx = 1;
   c->rx_pos = c->rx_buf;
-  c->rx_aux = NULL;
   rmove(s, c->pool);
   return 1;
 }