From cdf12d06bab6053c4e31d155a777fe2a2d90407d Mon Sep 17 00:00:00 2001 From: Simon Vrouwe Date: Mon, 20 Jun 2022 10:52:37 +0300 Subject: [PATCH] lightningd: Make sure plugins don't register the same option "name" The extra entry in opt_table would never be called, leaving plugins clueless why options keep defaulting. Note that option registration outside startup does nothing. Instead, dynamic plugins can use `plugin start [second_parameter]` to pass options. --- lightningd/plugin.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index b8564817b..07bb6fa01 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -886,10 +886,24 @@ char *plugin_opt_set(const char *arg, struct plugin_opt *popt) return NULL; } +/* Returns true if "name" was already registered and now overwritten. */ +static bool plugin_opt_register(struct plugin_opt *popt) +{ + bool was_registered = opt_unregister(popt->name); + if (streq(popt->type, "flag")) + opt_register_noarg(popt->name, plugin_opt_flag_set, popt, + popt->description); + else + opt_register_arg(popt->name, plugin_opt_set, NULL, popt, + popt->description); + + return was_registered; +} + static void destroy_plugin_opt(struct plugin_opt *opt) { - if (!opt_unregister(opt->name)) - fatal("Could not unregister %s", opt->name); + /* does nothing when "name" registration replaced its double */ + opt_unregister(opt->name); list_del(&opt->list); } @@ -978,13 +992,10 @@ static const char *plugin_opt_add(struct plugin *plugin, const char *buffer, list_add_tail(&plugin->plugin_opts, &popt->list); - if (streq(popt->type, "flag")) - opt_register_noarg(popt->name, plugin_opt_flag_set, popt, - popt->description); - - else - opt_register_arg(popt->name, plugin_opt_set, NULL, popt, - popt->description); + /* Command line options are parsed only during ld's startup and each "name" + * only once. Always registers to satisfy destructor */ + if (plugin_opt_register(popt) && plugin->plugins->startup) + fatal("error starting plugin '%s': option name '%s' is already taken", plugin->cmd, popt->name); tal_add_destructor(popt, destroy_plugin_opt); return NULL;