Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Important plugin #3890

Merged
merged 7 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@ include tools/Makefile
include plugins/Makefile
include tests/plugins/Makefile

# Generated from PLUGINS definition in plugins/Makefile
gen_list_of_builtin_plugins.h : plugins/Makefile Makefile
@echo GEN $@
@rm -f $@ || true
@echo 'static const char *list_of_builtin_plugins[] = {' >> $@
@echo '$(PLUGINS)' | sed 's@plugins/\([^ ]*\)@"\1",@g'>> $@
@echo 'NULL' >> $@
@echo '};' >> $@

# Git doesn't maintain timestamps, so we only regen if git says we should.
CHANGED_FROM_GIT = [ x"`git log $@ | head -n1`" != x"`git log $< | head -n1`" -o x"`git diff $<`" != x"" ]

Expand Down
19 changes: 16 additions & 3 deletions doc/lightningd-config.5
Original file line number Diff line number Diff line change
Expand Up @@ -534,10 +534,11 @@ add multiple directories\.


\fBclear-plugins\fR
This option clears all \fIplugin\fR and \fIplugin-dir\fR options preceeding it,
This option clears all \fIplugin\fR, \fIimportant-plugin\fR, and \fIplugin-dir\fR options
preceeding it,
including the default built-in plugin directory\. You can still add
\fIplugin-dir\fR and \fIplugin\fR options following this and they will have the
normal effect\.
\fIplugin-dir\fR, \fIplugin\fR, and \fIimportant-plugin\fR options following this
and they will have the normal effect\.


\fBdisable-plugin\fR=\fIPLUGIN\fR
Expand All @@ -547,6 +548,18 @@ be loaded at startup, whatever directory it is in\. This option is useful for
disabling a single plugin inside a directory\. You can still explicitly
load plugins which have been disabled, using \fBlightning-plugin\fR(7) \fBstart\fR\.


\fBimportant-plugin\fR=\fIPLUGIN\fR
Speciy a plugin to run as part of C-lightning\.
This can be specified multiple times to add multiple plugins\.
Plugins specified via this option are considered so important, that if the
plugin stops for any reason (including via \fBlightning-plugin\fR(7) \fBstop\fR),
C-lightning will also stop running\.
This way, you can monitor crashes of important plugins by simply monitoring
if C-lightning terminates\.
Built-in plugins, which are installed with \fBlightningd\fR(8), are automatically
considered important\.

.SH BUGS

You should report bugs on our github issues page, and maybe submit a fix
Expand Down
18 changes: 15 additions & 3 deletions doc/lightningd-config.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,11 @@ loaded. *DIRECTORY* must exist; this can be specified multiple times to
add multiple directories.

**clear-plugins**
This option clears all *plugin* and *plugin-dir* options preceeding it,
This option clears all *plugin*, *important-plugin*, and *plugin-dir* options
preceeding it,
including the default built-in plugin directory. You can still add
*plugin-dir* and *plugin* options following this and they will have the
normal effect.
*plugin-dir*, *plugin*, and *important-plugin* options following this
and they will have the normal effect.

**disable-plugin**=*PLUGIN*
If *PLUGIN* contains a /, plugins with the same path as *PLUGIN* will
Expand All @@ -451,6 +452,17 @@ be loaded at startup, whatever directory it is in. This option is useful for
disabling a single plugin inside a directory. You can still explicitly
load plugins which have been disabled, using lightning-plugin(7) `start`.

**important-plugin**=*PLUGIN*
Speciy a plugin to run as part of C-lightning.
This can be specified multiple times to add multiple plugins.
Plugins specified via this option are considered so important, that if the
plugin stops for any reason (including via lightning-plugin(7) `stop`),
C-lightning will also stop running.
This way, you can monitor crashes of important plugins by simply monitoring
if C-lightning terminates.
Built-in plugins, which are installed with lightningd(8), are automatically
considered important.

BUGS
----

Expand Down
3 changes: 3 additions & 0 deletions lightningd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ LIGHTNINGD_HEADERS = $(LIGHTNINGD_HEADERS_NOGEN) $(LIGHTNINGD_HEADERS_GEN) $(WAL

$(LIGHTNINGD_OBJS): $(LIGHTNINGD_HEADERS)

# Only the plugin component needs to depend on this header.
lightningd/plugin.o : gen_list_of_builtin_plugins.h

lightningd/gen_channel_state_names.h: lightningd/channel_state.h ccan/ccan/cdump/tools/cdump-enumstr
ccan/ccan/cdump/tools/cdump-enumstr lightningd/channel_state.h > $@

Expand Down
57 changes: 41 additions & 16 deletions lightningd/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
*/
ld->rpc_filemode = 0600;

/*~ This is the exit code to use on exit.
* Set to NULL meaning we are not interested in exiting yet.
*/
ld->exit_code = NULL;

return ld;
}

Expand Down Expand Up @@ -469,9 +474,9 @@ static const char *find_my_pkglibexec_path(struct lightningd *ld,

/*~ The plugin dir is in ../libexec/c-lightning/plugins, which (unlike
* those given on the command line) does not need to exist. */
add_plugin_dir(ld->plugins,
path_join(tmpctx, pkglibexecdir, "plugins"),
true);
plugins_set_builtin_plugins_dir(ld->plugins,
path_join(tmpctx,
pkglibexecdir, "plugins"));

/*~ Sometimes take() can be more efficient, since the routine can
* manipulate the string in place. This is the case here. */
Expand All @@ -484,10 +489,11 @@ static const char *find_daemon_dir(struct lightningd *ld, const char *argv0)
const char *my_path = find_my_directory(ld, argv0);
/* If we're running in-tree, all the subdaemons are with lightningd. */
if (has_all_subdaemons(my_path)) {
/* In this case, look in ../plugins */
add_plugin_dir(ld->plugins,
path_join(tmpctx, my_path, "../plugins"),
true);
/* In this case, look for built-in plugins in ../plugins */
plugins_set_builtin_plugins_dir(ld->plugins,
path_join(tmpctx,
my_path,
"../plugins"));
return my_path;
}

Expand Down Expand Up @@ -751,6 +757,14 @@ static void hsm_ecdh_failed(enum status_failreason fail,
fatal("hsm failure: %s", fmt);
}

/*~ This signals to the mainloop that some part wants to cleanly exit now. */
void lightningd_exit(struct lightningd *ld, int exit_code)
{
ld->exit_code = tal(ld, int);
*ld->exit_code = exit_code;
io_break(ld);
}

int main(int argc, char *argv[])
{
struct lightningd *ld;
Expand All @@ -763,6 +777,8 @@ int main(int argc, char *argv[])
struct ext_key *bip32_base;
struct rlimit nofile = {1024, 1024};

int exit_code = 0;

/*~ Make sure that we limit ourselves to something reasonable. Modesty
* is a virtue. */
setrlimit(RLIMIT_NOFILE, &nofile);
Expand Down Expand Up @@ -1002,10 +1018,17 @@ int main(int argc, char *argv[])
assert(io_loop_ret == ld);
ld->state = LD_STATE_SHUTDOWN;

/* Keep this fd around, to write final response at the end. */
stop_fd = io_conn_fd(ld->stop_conn);
io_close_taken_fd(ld->stop_conn);
stop_response = tal_steal(NULL, ld->stop_response);
/* Were we exited via `lightningd_exit`? */
if (ld->exit_code) {
exit_code = *ld->exit_code;
stop_fd = -1;
stop_response = NULL;
} else {
/* Keep this fd around, to write final response at the end. */
stop_fd = io_conn_fd(ld->stop_conn);
io_close_taken_fd(ld->stop_conn);
stop_response = tal_steal(NULL, ld->stop_response);
}

shutdown_subdaemons(ld);

Expand Down Expand Up @@ -1040,11 +1063,13 @@ int main(int argc, char *argv[])

daemon_shutdown();

/* Finally, send response to shutdown command */
write_all(stop_fd, stop_response, strlen(stop_response));
close(stop_fd);
tal_free(stop_response);
/* Finally, send response to shutdown command if appropriate. */
if (stop_fd >= 0) {
write_all(stop_fd, stop_response, strlen(stop_response));
close(stop_fd);
tal_free(stop_response);
}

/*~ Farewell. Next stop: hsmd/hsmd.c. */
return 0;
return exit_code;
}
10 changes: 10 additions & 0 deletions lightningd/lightningd.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ struct lightningd {
/* Total number of coin moves we've seen, since
* coin move tracking was cool */
s64 coin_moves_count;

/* If non-NULL, contains the exit code to use. */
int *exit_code;
};

/* Turning this on allows a tal allocation to return NULL, rather than aborting.
Expand All @@ -289,4 +292,11 @@ void test_subdaemons(const struct lightningd *ld);
/* Notify lightningd about new blocks. */
void notify_new_block(struct lightningd *ld, u32 block_height);

/* Signal a clean exit from lightningd.
* NOTE! This function **returns**.
* This just causes the main loop to exit, so you have to return
* all the way to the main loop for `lightningd` to exit.
*/
void lightningd_exit(struct lightningd *ld, int exit_code);

#endif /* LIGHTNING_LIGHTNINGD_LIGHTNINGD_H */
23 changes: 22 additions & 1 deletion lightningd/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ static char *opt_add_plugin(const char *arg, struct lightningd *ld)
log_info(ld->log, "%s: disabled via disable-plugin", arg);
return NULL;
}
plugin_register(ld->plugins, arg, NULL);
plugin_register(ld->plugins, arg, NULL, false);
return NULL;
}

Expand All @@ -369,6 +369,16 @@ static char *opt_clear_plugins(struct lightningd *ld)
return NULL;
}

static char *opt_important_plugin(const char *arg, struct lightningd *ld)
{
if (plugin_blacklisted(ld->plugins, arg)) {
log_info(ld->log, "%s: disabled via disable-plugin", arg);
return NULL;
}
plugin_register(ld->plugins, arg, NULL, true);
return NULL;
}

/* Prompt the user to enter a password, from which will be derived the key used
* for `hsm_secret` encryption.
* The algorithm used to derive the key is Argon2(id), to which libsodium
Expand Down Expand Up @@ -556,6 +566,10 @@ static void dev_register_opts(struct lightningd *ld)
opt_register_noarg("--dev-no-version-checks", opt_set_bool,
&ld->dev_no_version_checks,
"Skip calling subdaemons with --version on startup");
opt_register_early_noarg("--dev-builtin-plugins-unimportant",
opt_set_bool,
&ld->plugins->dev_builtin_plugins_unimportant,
"Make builtin plugins unimportant so you can plugin stop them.");
}
#endif /* DEVELOPER */

Expand Down Expand Up @@ -771,6 +785,10 @@ static void register_opts(struct lightningd *ld)
NULL, ld,
"Disable a particular plugin by filename/name");

opt_register_early_arg("--important-plugin", opt_important_plugin,
NULL, ld,
"Add an important plugin to be run (can be used multiple times). Die if the plugin dies.");

/* Early, as it suppresses DNS lookups from cmdline too. */
opt_register_early_arg("--always-use-proxy",
opt_set_bool_arg, opt_show_bool,
Expand Down Expand Up @@ -1278,6 +1296,9 @@ static void add_config(struct lightningd *ld,
json_add_opt_log_levels(response, ld->log);
} else if (opt->cb_arg == (void *)opt_disable_plugin) {
json_add_opt_disable_plugins(response, ld->plugins);
} else if (opt->cb_arg == (void *)opt_important_plugin) {
/* Do nothing, this is already handled by
* opt_add_plugin. */
} else if (opt->cb_arg == (void *)opt_add_plugin_dir
|| opt->cb_arg == (void *)plugin_opt_set
|| opt->cb_arg == (void *)plugin_opt_flag_set) {
Expand Down
Loading