From 5f6a742d81abc922a278e9d58d553eafe0a852d6 Mon Sep 17 00:00:00 2001 From: Simon Vrouwe Date: Tue, 3 Jan 2023 17:28:22 +0200 Subject: [PATCH] lightningd: in second shutdown_plugin, trigger EOF in plugin stdin So a db_write plugin can still self-terminate when its ready for it. Credit to ZmnSCPxj for the EOF idea, see issue #4785 --- lightningd/plugin.c | 15 +++++++++++---- lightningd/plugin.h | 13 +++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 57b715e867d4..d7e26de1c6d8 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -2167,8 +2167,9 @@ void shutdown_plugins(struct lightningd *ld, bool first_call) continue; } - /* First call: Send shutdown notification while jsonrpc still exists */ + /* First call: */ if (first_call) { + /* Send shutdown notifications to all while jsonrpc still exists */ notified = notify_plugin_shutdown(ld, p); /* Always keep db_write plugins alive in first call */ @@ -2181,10 +2182,16 @@ void shutdown_plugins(struct lightningd *ld, bool first_call) else tal_free(p); - /* Second call: Only wait if plugin got notified in first call */ + /* Second call: */ } else { - p->plugin_state = SHUTDOWN; - if (!plugin_subscriptions_contains(p, "shutdown")) + /* Only wait if the plugin got notified in first call */ + if (plugin_subscriptions_contains(p, "shutdown")) { + p->plugin_state = SHUTDOWN; + + /* io_close triggers EOF at plugin's stdin read-loop, so it can + * still self-terminate when its ready (within 30s). */ + io_close(p->stdin_conn); + } else tal_free(p); } } diff --git a/lightningd/plugin.h b/lightningd/plugin.h index 39a190e11254..20abe7037cd9 100644 --- a/lightningd/plugin.h +++ b/lightningd/plugin.h @@ -240,12 +240,17 @@ void plugin_kill(struct plugin *plugin, enum log_level loglevel, const char *fmt, ...); /** - * Tell plugins we're shutting down, and free them. + * Tell plugins we're shutting down, maybe wait for them to self-terminate and + * free them. * - * @skip_db_write_plugins - keep db_write plugins alive, i.e. the ones that - * registered the db_write hook + * @first_call=true: keeps db_write plugins alive, i.e. the ones that + * registered the db_write hook, but they still receive a shutdown notification. + * + * @first_call=false: shutdown remaining plugins: if it subscribed to shutdown + * then trigger EOF on stdin and wait for it to self-terminate, otherwise kill + * it immediately. */ -void shutdown_plugins(struct lightningd *ld, bool first); +void shutdown_plugins(struct lightningd *ld, bool first_call); /** * Returns the plugin which registers the command with name {cmd_name}