From 42c9aa1a5f683fbee50b84a1cd677814ba97f98a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 13 Sep 2022 06:49:12 +0930 Subject: [PATCH] libplugin: forget pending requests if associated command freed. This is usually fine, but without this, commando (another branch!) has a race: 1. A command has multiple parts. 2. We start sending them out. 3. We get a response, which completes the cmd. 4. We go to send the next one out, but it's been freed. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 171c7d046..c7b03989c 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -173,6 +173,11 @@ static const char *get_json_id(const tal_t *ctx, plugin->next_outreq_id++); } +static void destroy_out_req(struct out_req *out_req, struct plugin *plugin) +{ + strmap_del(&plugin->out_reqs, out_req->id, NULL); +} + /* FIXME: Move lightningd/jsonrpc to common/ ? */ struct out_req * @@ -190,13 +195,14 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, { struct out_req *out; - out = tal(plugin, struct out_req); + out = tal(cmd, struct out_req); out->id = get_json_id(out, plugin, cmd ? cmd->id : NULL, method); out->cmd = cmd; out->cb = cb; out->errcb = errcb; out->arg = arg; strmap_add(&plugin->out_reqs, out->id, out); + tal_add_destructor2(out, destroy_out_req, plugin); /* If command goes away, don't call callbacks! */ if (out->cmd) @@ -684,7 +690,6 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) /* We want to free this if callback doesn't. */ tal_steal(tmpctx, out); - strmap_del(&plugin->out_reqs, out->id, NULL); contenttok = json_get_member(plugin->rpc_buffer, toks, "error"); if (contenttok) {