From 1e4f85a5395e28b98b353dd57b4f796013f38b9f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 5 May 2020 10:43:34 +0930 Subject: [PATCH] lightningd: refactor to extract getmanifest paths. This will allow the dynamic starting code to use them too. Also lets us move dev_debug_subprocess under #if DEVELOPER. Signed-off-by: Rusty Russell --- lightningd/lightningd.c | 4 +- lightningd/lightningd.h | 6 +- lightningd/plugin.c | 111 ++++++++++++++++---------- lightningd/plugin.h | 16 +++- lightningd/test/run-find_my_abspath.c | 2 +- 5 files changed, 87 insertions(+), 52 deletions(-) diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 2b0ded7e7..2013501be 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -123,8 +123,8 @@ static struct lightningd *new_lightningd(const tal_t *ctx) * is a nod to keeping it minimal and explicit: we need this code for * testing, but its existence means we're not actually testing the * same exact code users will be running. */ - ld->dev_debug_subprocess = NULL; #if DEVELOPER + ld->dev_debug_subprocess = NULL; ld->dev_disconnect_fd = -1; ld->dev_subdaemon_fail = false; ld->dev_allow_localhost = false; @@ -808,7 +808,7 @@ int main(int argc, char *argv[]) /*~ Initialize all the plugins we just registered, so they can * do their thing and tell us about themselves (including * options registration). */ - plugins_init(ld->plugins, ld->dev_debug_subprocess); + plugins_init(ld->plugins); /*~ Handle options and config. */ handle_opts(ld, argc, argv); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 2a9f9ad1e..d33b49d1a 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -200,15 +200,15 @@ struct lightningd { * if we are the fundee. */ u32 max_funding_unconfirmed; - /* If we want to debug a subdaemon/plugin. */ - const char *dev_debug_subprocess; - /* RPC which asked us to shutdown, if non-NULL */ struct io_conn *stop_conn; /* RPC response to send once we've shut down. */ const char *stop_response; #if DEVELOPER + /* If we want to debug a subdaemon/plugin. */ + const char *dev_debug_subprocess; + /* If we have a --dev-disconnect file */ int dev_disconnect_fd; diff --git a/lightningd/plugin.c b/lightningd/plugin.c index a833c401b..23ba4d056 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -1188,60 +1188,85 @@ void plugins_add_default_dir(struct plugins *plugins) } } -void plugins_init(struct plugins *plugins, const char *dev_plugin_debug) +bool plugin_send_getmanifest(struct plugin *p) { - struct plugin *p; char **cmd; int stdin, stdout; struct jsonrpc_request *req; + bool debug = false; +#if DEVELOPER + if (p->plugins->ld->dev_debug_subprocess + && strends(p->cmd, p->plugins->ld->dev_debug_subprocess)) + debug = true; +#endif + cmd = tal_arrz(tmpctx, char *, 2 + debug); + cmd[0] = p->cmd; + if (debug) + cmd[1] = "--debugger"; + p->pid = pipecmdarr(&stdin, &stdout, &pipecmd_preserve, cmd); + if (p->pid == -1) + return false; + + log_debug(p->plugins->log, "started(%u) %s", p->pid, p->cmd); + p->buffer = tal_arr(p, char, 64); + p->stop = false; + + /* Create two connections, one read-only on top of p->stdout, and one + * write-only on p->stdin */ + io_new_conn(p, stdout, plugin_stdout_conn_init, p); + io_new_conn(p, stdin, plugin_stdin_conn_init, p); + req = jsonrpc_request_start(p, "getmanifest", p->log, + plugin_manifest_cb, p); + jsonrpc_request_end(req); + plugin_request_send(p, req); + p->plugin_state = AWAITING_GETMANIFEST_RESPONSE; + + /* Don't timeout if they're running a debugger. */ + if (debug) + p->timeout_timer = NULL; + else { + p->timeout_timer + = new_reltimer(p->plugins->ld->timers, p, + time_from_sec(PLUGIN_MANIFEST_TIMEOUT), + plugin_manifest_timeout, p); + } + + return true; +} + +bool plugins_send_getmanifest(struct plugins *plugins) +{ + struct plugin *p, *next; + bool sent = false; + + /* Spawn the plugin processes before entering the io_loop */ + list_for_each_safe(&plugins->plugins, p, next, list) { + if (p->plugin_state != UNCONFIGURED) + continue; + if (plugin_send_getmanifest(p)) { + sent = true; + continue; + } + if (plugins->startup) + fatal("error starting plugin '%s': %s", p->cmd, + strerror(errno)); + plugin_kill(p, "error starting: %s", strerror(errno)); + tal_free(p); + } + + return sent; +} + +void plugins_init(struct plugins *plugins) +{ plugins->default_dir = path_join(plugins, plugins->ld->config_basedir, "plugins"); plugins_add_default_dir(plugins); setenv("LIGHTNINGD_PLUGIN", "1", 1); setenv("LIGHTNINGD_VERSION", version(), 1); - /* Spawn the plugin processes before entering the io_loop */ - list_for_each(&plugins->plugins, p, list) { - bool debug; - debug = dev_plugin_debug && strends(p->cmd, dev_plugin_debug); - cmd = tal_arrz(p, char *, 2 + debug); - cmd[0] = p->cmd; - if (debug) - cmd[1] = "--debugger"; - p->pid = pipecmdarr(&stdin, &stdout, &pipecmd_preserve, cmd); - - if (p->pid == -1) - fatal("error starting plugin '%s': %s", p->cmd, - strerror(errno)); - else - log_debug(plugins->log, "started(%u) %s", p->pid, p->cmd); - p->buffer = tal_arr(p, char, 64); - p->stop = false; - - /* Create two connections, one read-only on top of p->stdout, and one - * write-only on p->stdin */ - io_new_conn(p, stdout, plugin_stdout_conn_init, p); - io_new_conn(p, stdin, plugin_stdin_conn_init, p); - req = jsonrpc_request_start(p, "getmanifest", p->log, - plugin_manifest_cb, p); - jsonrpc_request_end(req); - plugin_request_send(p, req); - p->plugin_state = AWAITING_GETMANIFEST_RESPONSE; - - /* Don't timeout if they're running a debugger. */ - if (debug) - p->timeout_timer = NULL; - else { - p->timeout_timer - = new_reltimer(plugins->ld->timers, p, - time_from_sec(PLUGIN_MANIFEST_TIMEOUT), - plugin_manifest_timeout, p); - } - tal_free(cmd); - } - - if (plugins_any_in_state(plugins, AWAITING_GETMANIFEST_RESPONSE)) + if (plugins_send_getmanifest(plugins)) io_loop_with_timers(plugins->ld); } diff --git a/lightningd/plugin.h b/lightningd/plugin.h index 753ec2b0f..f9dad419f 100644 --- a/lightningd/plugin.h +++ b/lightningd/plugin.h @@ -144,10 +144,8 @@ void plugins_add_default_dir(struct plugins *plugins); * arguments. In order to read the getmanifest reply from the plugins * we spin up our own io_loop that exits once all plugins have * responded. - * - * The dev_plugin_debug arg comes from --dev-debugger if DEVELOPER. */ -void plugins_init(struct plugins *plugins, const char *dev_plugin_debug); +void plugins_init(struct plugins *plugins); /** * Free all resources that are held by plugins in the correct order. @@ -196,6 +194,18 @@ bool plugin_paths_match(const char *cmd, const char *name); */ bool plugin_remove(struct plugins *plugins, const char *name); +/** + * Kick of initialization of a plugin. + */ +bool plugin_send_getmanifest(struct plugin *p); + +/** + * Kick of initialization of all plugins which need it/ + * + * Return true if any were started. + */ +bool plugins_send_getmanifest(struct plugins *plugins); + /** * Kill a plugin process, with an error message. */ diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 78382bb54..f476cc0ea 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -194,7 +194,7 @@ void plugins_config(struct plugins *plugins UNNEEDED) void plugins_free(struct plugins *plugins UNNEEDED) { fprintf(stderr, "plugins_free called!\n"); abort(); } /* Generated stub for plugins_init */ -void plugins_init(struct plugins *plugins UNNEEDED, const char *dev_plugin_debug UNNEEDED) +void plugins_init(struct plugins *plugins UNNEEDED) { fprintf(stderr, "plugins_init called!\n"); abort(); } /* Generated stub for plugins_new */ struct plugins *plugins_new(const tal_t *ctx UNNEEDED, struct log_book *log_book UNNEEDED,