diff options
author | Maria Matejka <mq@ucw.cz> | 2023-01-19 10:53:09 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2023-01-19 11:03:31 +0100 |
commit | 59a5bf18f997e11a3e3ddd70d59f597f77fa2b6c (patch) | |
tree | f0a4640ffb2f812a872a44fd512e7ba981fd09c2 | |
parent | 34aeafbf9ea98c8644f6403b3810ff0490350465 (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.c | 11 | ||||
-rw-r--r-- | nest/cli.h | 4 | ||||
-rw-r--r-- | nest/rt-show.c | 1 | ||||
-rw-r--r-- | sysdep/unix/main.c | 11 |
4 files changed, 19 insertions, 8 deletions
@@ -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); } @@ -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); } |