From fa993926181f8c607fbb1e86c3fe1f7e7bacf5e9 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 9 Sep 2022 15:22:16 -0500 Subject: [PATCH] Fix problem with Glib 2.73.2+ and SIGCHLD handler This code fix is by Stefan Monnier (Bug#57699). * src/process.c (init_process_emacs) [HAVE_GLIB && !WINDOWSNT]: Adjust to Glib 2.73.2 behavior change on Linux kernel 5.3+. --- src/process.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/process.c b/src/process.c index 7a133cda00f..358899cdede 100644 --- a/src/process.c +++ b/src/process.c @@ -7391,7 +7391,8 @@ child_signal_notify (void) } /* LIB_CHILD_HANDLER is a SIGCHLD handler that Emacs calls while doing - its own SIGCHLD handling. On POSIXish systems, glib needs this to + its own SIGCHLD handling. On POSIXish systems lacking + pidfd_open+waitid or using Glib 2.73.1-, Glib needs this to keep track of its own children. GNUstep is similar. */ static void dummy_handler (int sig) {} @@ -8358,7 +8359,7 @@ DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0, #ifdef subprocesses /* Arrange to catch SIGCHLD if this hasn't already been arranged. - Invoke this after init_process_emacs, and after glib and/or GNUstep + Invoke this after init_process_emacs, and after Glib and/or GNUstep futz with the SIGCHLD handler, but before Emacs forks any children. This function's caller should block SIGCHLD. */ @@ -8423,26 +8424,35 @@ init_process_emacs (int sockfd) if (!will_dump_with_unexec_p ()) { #if defined HAVE_GLIB && !defined WINDOWSNT - /* Tickle glib's child-handling code. Ask glib to install a + /* Tickle Glib's child-handling code. Ask Glib to install a watch source for Emacs itself which will initialize glib's private SIGCHLD handler, allowing catch_child_signal to copy - it into lib_child_handler. + it into lib_child_handler. This is a hacky workaround to get + glib's g_unix_signal_handler into lib_child_handler. - Unfortunately in glib commit 2e471acf, the behavior changed to + In Glib 2.37.5 (2013), commit 2e471acf changed Glib to always install a signal handler when g_child_watch_source_new - is called and not just the first time it's called. Glib also - now resets signal handlers to SIG_DFL when it no longer has a - watcher on that signal. This is a hackey work around to get - glib's g_unix_signal_handler into lib_child_handler. */ + is called and not just the first time it's called, and to + reset signal handlers to SIG_DFL when it no longer has a + watcher on that signal. Arrange for Emacs's signal handler + to be reinstalled even if this happens. + + In Glib 2.73.2 (2022), commit f615eef4 changed Glib again, + to not install a signal handler if the system supports + pidfd_open and waitid (as in Linux kernel 5.3+). The hacky + workaround is not needed in this case. */ GSource *source = g_child_watch_source_new (getpid ()); catch_child_signal (); g_source_unref (source); - eassert (lib_child_handler != dummy_handler); - signal_handler_t lib_child_handler_glib = lib_child_handler; - catch_child_signal (); - eassert (lib_child_handler == dummy_handler); - lib_child_handler = lib_child_handler_glib; + if (lib_child_handler != dummy_handler) + { + /* The hacky workaround is needed on this platform. */ + signal_handler_t lib_child_handler_glib = lib_child_handler; + catch_child_signal (); + eassert (lib_child_handler == dummy_handler); + lib_child_handler = lib_child_handler_glib; + } #else catch_child_signal (); #endif -- 2.39.2