From 1d4a1cdd8a294e799a7234a8d0da1ddbf5e0a36b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 20 Nov 2025 12:07:13 +1030 Subject: [PATCH] libplugin: don't wait for clean_tmpctx() to free requests as we process them. xpay is relying on the destructor to send another request. This means that it doesn't actually submit the request until *next time* we wake. This has been in xpay from the start, but it is not noticeable until xpay stops subscribing to every command on the rpc_command hook. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 8dfba2ce5..22d499540 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -1018,7 +1018,8 @@ static void destroy_cmd_mark_freed(struct command *cmd, bool *cmd_freed) *cmd_freed = true; } -static void handle_rpc_reply(struct plugin *plugin, const char *buf, const jsmntok_t *toks) +static void handle_rpc_reply(const tal_t *working_ctx, + struct plugin *plugin, const char *buf, const jsmntok_t *toks) { const jsmntok_t *idtok, *contenttok; struct out_req *out; @@ -1042,7 +1043,7 @@ static void handle_rpc_reply(struct plugin *plugin, const char *buf, const jsmnt } /* We want to free this if callback doesn't. */ - tal_steal(tmpctx, out); + tal_steal(working_ctx, out); /* If they return complete, cmd should have been freed! */ cmd_freed = false; @@ -1356,6 +1357,8 @@ static void rpc_conn_finished(struct io_conn *conn, static struct io_plan *rpc_conn_read_response(struct io_conn *conn, struct plugin *plugin) { + const tal_t *working_ctx = tal(NULL, char); + /* Gather an parse any new bytes */ for (;;) { const jsmntok_t *toks; @@ -1371,10 +1374,14 @@ static struct io_plan *rpc_conn_read_response(struct io_conn *conn, if (!toks) break; - handle_rpc_reply(plugin, buf, toks); + handle_rpc_reply(working_ctx, plugin, buf, toks); jsonrpc_io_parse_done(plugin->jsonrpc_in); } + /* Explicitly free any expired requests now; xpay uses this to + * fire more commands! */ + tal_free(working_ctx); + /* Read more */ return jsonrpc_io_read(conn, plugin->jsonrpc_in, rpc_conn_read_response,