From ee0c13eefe442de69c27a23f7cd557b4970c532d Mon Sep 17 00:00:00 2001 From: ZmnSCPxj jxPCSnmZ Date: Mon, 23 Nov 2020 11:46:13 +0800 Subject: [PATCH] lightningd/plugin.c: Make plugin-exclusive loop support multiple plugins. --- lightningd/plugin.c | 20 ++++++++++++++------ lightningd/plugin.h | 10 +++++++--- lightningd/plugin_hook.c | 15 +++++++++++---- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 75d12a8a299e..f28ab277efc2 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -1715,20 +1715,28 @@ void plugin_request_send(struct plugin *plugin, req->stream = NULL; } -void *plugin_exclusive_loop(struct plugin *plugin) +void *plugins_exclusive_loop(struct plugin **plugins) { void *ret; + size_t i; + bool last = false; + assert(tal_count(plugins) != 0); - io_conn_out_exclusive(plugin->stdin_conn, true); - io_conn_exclusive(plugin->stdout_conn, true); + for (i = 0; i < tal_count(plugins); ++i) { + io_conn_out_exclusive(plugins[i]->stdin_conn, true); + io_conn_exclusive(plugins[i]->stdout_conn, true); + } /* We don't service timers here, either! */ ret = io_loop(NULL, NULL); - io_conn_out_exclusive(plugin->stdin_conn, false); - if (io_conn_exclusive(plugin->stdout_conn, false)) + for (i = 0; i < tal_count(plugins); ++i) { + io_conn_out_exclusive(plugins[i]->stdin_conn, false); + last = io_conn_exclusive(plugins[i]->stdout_conn, false); + } + if (last) fatal("Still io_exclusive after removing plugin %s?", - plugin->cmd); + plugins[tal_count(plugins) - 1]->cmd); return ret; } diff --git a/lightningd/plugin.h b/lightningd/plugin.h index 070c0184ad8e..6f9c7ab667ea 100644 --- a/lightningd/plugin.h +++ b/lightningd/plugin.h @@ -304,12 +304,16 @@ void json_add_opt_disable_plugins(struct json_stream *response, const struct plugins *plugins); /** - * Used by db hooks which can't have any other I/O while talking to plugin. + * Used by db hooks which can't have any other I/O while talking to + * hooked plugins. * - * Returns output of io_loop() (ie. whatever gets passed to io_break() + * @param plugins - a `tal`-allocated array of plugins that are the + * only ones we talk to. + * + * @return output of io_loop() (ie. whatever gets passed to io_break() * to end exclusive loop). */ -void *plugin_exclusive_loop(struct plugin *plugin); +void *plugins_exclusive_loop(struct plugin **plugins); /** * Add a directory to the plugin path to automatically load plugins. diff --git a/lightningd/plugin_hook.c b/lightningd/plugin_hook.c index 321cb75fec53..9413fa3047b8 100644 --- a/lightningd/plugin_hook.c +++ b/lightningd/plugin_hook.c @@ -330,12 +330,18 @@ void plugin_hook_db_sync(struct db *db) struct jsonrpc_request *req; struct plugin_hook_request *ph_req; void *ret; - struct plugin *plugin; + struct plugin **plugins; + size_t i; const char **changes = db_changes(db); if (tal_count(hook->hooks) == 0) return; + plugins = notleak(tal_arr(NULL, struct plugin *, + tal_count(hook->hooks))); + for (i = 0; i < tal_count(hook->hooks); ++i) + plugins[i] = hook->hooks[i]->plugin; + ph_req = notleak(tal(hook->hooks, struct plugin_hook_request)); /* FIXME: do IO logging for this! */ req = jsonrpc_request_start(NULL, hook->name, NULL, NULL, @@ -344,7 +350,7 @@ void plugin_hook_db_sync(struct db *db) ph_req->hook = hook; ph_req->db = db; - plugin = ph_req->plugin = hook->hooks[0]->plugin; + ph_req->plugin = hook->hooks[0]->plugin; json_add_num(req->stream, "data_version", db_data_version_get(db)); @@ -359,12 +365,13 @@ void plugin_hook_db_sync(struct db *db) /* We can be called on way out of an io_loop, which is already breaking. * That will make this immediately return; save the break value and call * again, then hand it onwards. */ - ret = plugin_exclusive_loop(plugin); + ret = plugins_exclusive_loop(plugins); if (ret != ph_req) { - void *ret2 = plugin_exclusive_loop(plugin); + void *ret2 = plugins_exclusive_loop(plugins); assert(ret2 == ph_req); io_break(ret); } + tal_free(plugins); } static void add_deps(const char ***arr,