diff --git a/CHANGELOG.md b/CHANGELOG.md index c413d26d6005..24bc647f2e2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ Note: You should always set `allow-deprecated-apis=false` to test for changes. - renepay: fixes a race condition that leads to **BROKEN** plugin-cln-renepay: Unable to parse sendpay_failure ([#8798]) - fuzz: fix build with newer clang. ([#8717]) - Plugins: `bkpr_listbalances` no longer crashes if we lost our db, then do emergencyrecover and close a channel. ([#8890]) + - Plugins: now wait for all plugins to gracefully shutdown instead of killing remaining plugins when one exits first. ([#7697]) - lightningd: possible crash when peers disconnected if there was more than one plugin servicing the `peer_connected` hook. ([#8889]) - JSON-RPC: `decode` is now more informative with malformed strings (won't claim everything is a malformed rune!). ([#8814]) - reckless search now returns partial matches instead of requiring exact plugin names. ([#8762]) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 447eb59d7cde..35bda53c92b1 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -2602,8 +2602,15 @@ void shutdown_plugins(struct lightningd *ld) timers_init(timer, time_mono()); new_reltimer(timer, timer, time_from_sec(30), NULL, NULL); - void *ret = io_loop(timer, &expired); - assert(ret == NULL || ret == destroy_plugin); + /* Keep looping while plugins are still shutting down. + * io_loop can return early when one plugin exits (e.g. + * num_fds drops to 0) but others may still need time. */ + while (!list_empty(&ld->plugins->plugins)) { + void *ret = io_loop(timer, &expired); + /* Timer expired, stop waiting. */ + if (expired) + break; + } /* Report and free remaining plugins. */ while (!list_empty(&ld->plugins->plugins)) {