summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2023-01-19 10:53:09 +0100
committerMaria Matejka <mq@ucw.cz>2023-01-19 11:03:31 +0100
commit59a5bf18f997e11a3e3ddd70d59f597f77fa2b6c (patch)
treef0a4640ffb2f812a872a44fd512e7ba981fd09c2
parent34aeafbf9ea98c8644f6403b3810ff0490350465 (diff)
CLI closing fix when its action is run asynchronously.
Some CLI actions, notably "show route", are run by queuing an event somewhere else. If the user closes the socket, in case such an action is being executed, the CLI must free the socket immediately from the error hook but the pool must remain until the asynchronous event finishes and cleans everything up.
-rw-r--r--nest/cli.c11
-rw-r--r--nest/cli.h4
-rw-r--r--nest/rt-show.c1
-rw-r--r--sysdep/unix/main.c11
4 files changed, 19 insertions, 8 deletions
diff --git a/nest/cli.c b/nest/cli.c
index 469d45b6..1debfccf 100644
--- a/nest/cli.c
+++ b/nest/cli.c
@@ -307,14 +307,14 @@ cli_event(void *data)
}
cli *
-cli_new(void *priv)
+cli_new(struct birdsock *sock)
{
pool *p = rp_new(cli_pool, "CLI");
cli *c = mb_alloc(p, sizeof(cli));
bzero(c, sizeof(cli));
c->pool = p;
- c->priv = priv;
+ c->sock = sock;
c->event = ev_new(p);
c->event->hook = cli_event;
c->event->data = c;
@@ -415,7 +415,12 @@ cli_free(cli *c)
if (c == cmd_reconfig_stored_cli)
cmd_reconfig_stored_cli = NULL;
- if (!defer)
+ if (defer)
+ {
+ rfree(c->sock);
+ c->sock = NULL;
+ }
+ else
rfree(c->pool);
}
diff --git a/nest/cli.h b/nest/cli.h
index 92572968..2b96da5b 100644
--- a/nest/cli.h
+++ b/nest/cli.h
@@ -28,7 +28,7 @@ struct cli_out {
typedef struct cli {
node n; /* Node in list of all log hooks */
pool *pool;
- void *priv; /* Private to sysdep layer */
+ struct birdsock *sock; /* Underlying socket */
byte *rx_buf, *rx_pos, *rx_aux; /* sysdep */
struct cli_out *tx_buf, *tx_pos, *tx_write;
event *event;
@@ -63,7 +63,7 @@ static inline void cli_separator(cli *c)
/* Functions provided to sysdep layer */
-cli *cli_new(void *);
+cli *cli_new(struct birdsock *);
void cli_init(void);
void cli_free(cli *);
void cli_kick(cli *);
diff --git a/nest/rt-show.c b/nest/rt-show.c
index dc88047a..d8eb2174 100644
--- a/nest/rt-show.c
+++ b/nest/rt-show.c
@@ -233,6 +233,7 @@ static int
rt_show_cleanup(struct cli *c)
{
struct rt_show_data *d = c->rover;
+ c->cleanup = NULL;
/* Cancel the feed */
if (d->req.hook)
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index bf9f2be0..74827d98 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -395,7 +395,8 @@ static char *path_control_socket = PATH_CONTROL_SOCKET;
static void
cli_write(cli *c)
{
- sock *s = c->priv;
+ sock *s = c->sock;
+ ASSERT_DIE(c->sock);
while (c->tx_pos)
{
@@ -419,7 +420,9 @@ cli_write(cli *c)
void
cli_write_trigger(cli *c)
{
- sock *s = c->priv;
+ sock *s = c->sock;
+ if (!s)
+ return;
if (s->tbuf == NULL)
cli_write(c);
@@ -434,7 +437,8 @@ cli_tx(sock *s)
int
cli_get_command(cli *c)
{
- sock *s = c->priv;
+ sock *s = c->sock;
+ ASSERT_DIE(c->sock);
byte *t = c->rx_aux ? : s->rbuf;
byte *tend = s->rpos;
byte *d = c->rx_pos;
@@ -477,6 +481,7 @@ cli_err(sock *s, int err)
else
log(L_INFO "CLI connection closed");
}
+
cli_free(s->data);
}