From ae4623c21a30e2b32e0cc17989fec71398a9d210 Mon Sep 17 00:00:00 2001 From: Simon Vrouwe Date: Mon, 8 Nov 2021 18:19:20 +0200 Subject: [PATCH] lightingd: removal of sigchild_handler in shutdown now also closes its pipe Setting SIGCHLD back to default (i.e. ignored) makes waitpid hang on an old SIGCHLD that was still in the pipe? This happens running test_important_plugin with developer=1: (or with dev=0 and build-in plugins subscribed to "shutdown") 0 0x00007ff8336b6437 in __GI___waitpid (pid=-1, stat_loc=0x0, options=1) at ../sysdeps/unix/sysv/linux/waitpid.c:30 1 0x000055fb468f733a in sigchld_rfd_in (conn=0x55fb47c7cfc8, ld=0x55fb47bdce58) at lightningd/lightningd.c:785 2 0x000055fb469bcc6b in next_plan (conn=0x55fb47c7cfc8, plan=0x55fb47c7cfe8) at ccan/ccan/io/io.c:59 3 0x000055fb469bd80b in do_plan (conn=0x55fb47c7cfc8, plan=0x55fb47c7cfe8, idle_on_epipe=false) at ccan/ccan/io/io.c:407 4 0x000055fb469bd849 in io_ready (conn=0x55fb47c7cfc8, pollflags=1) at ccan/ccan/io/io.c:417 5 0x000055fb469bfa26 in io_loop (timers=0x55fb47c41198, expired=0x7ffdf4be9028) at ccan/ccan/io/poll.c:453 6 0x000055fb468f1be9 in io_loop_with_timers (ld=0x55fb47bdce58) at lightningd/io_loop_with_timers.c:21 7 0x000055fb46924817 in shutdown_plugins (ld=0x55fb47bdce58) at lightningd/plugin.c:2114 8 0x000055fb468f7c92 in main (argc=22, argv=0x7ffdf4be9228) at lightningd/lightningd.c:1195 --- lightningd/lightningd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 5a9cc58a6..3df71745c 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -757,13 +757,14 @@ static int setup_sig_handlers(void) /*~ This removes the SIGCHLD handler, so we don't try to write * to a broken pipe. */ -static void remove_sigchild_handler(void) +static void remove_sigchild_handler(struct io_conn *sigchld_conn) { struct sigaction sigchild; memset(&sigchild, 0, sizeof(struct sigaction)); sigchild.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sigchild, NULL); + io_close(sigchld_conn); } /*~ This is the routine which sets up the sigchild handling. We just @@ -854,6 +855,7 @@ int main(int argc, char *argv[]) struct htlc_in_map *unconnected_htlcs_in; struct ext_key *bip32_base; int sigchld_rfd; + struct io_conn *sigchld_conn; int exit_code = 0; char **orig_argv; bool try_reexec; @@ -1099,10 +1101,8 @@ int main(int argc, char *argv[]) * "funding transaction spent" event which creates it. */ onchaind_replay_channels(ld); - /*~ Now handle sigchld, so we can clean up appropriately. - * We don't keep a pointer to this, so our simple leak detection - * code gets upset unless we mark it notleak(). */ - notleak(io_new_conn(ld, sigchld_rfd, sigchld_rfd_in, ld)); + /*~ Now handle sigchld, so we can clean up appropriately. */ + sigchld_conn = notleak(io_new_conn(ld, sigchld_rfd, sigchld_rfd_in, ld)); /*~ Mark ourselves live. * @@ -1189,7 +1189,7 @@ int main(int argc, char *argv[]) stop_topology(ld->topology); /* We're not going to collect our children. */ - remove_sigchild_handler(); + remove_sigchild_handler(sigchld_conn); shutdown_subdaemons(ld); /* Tell plugins we're shutting down, closes the db for write access. */