aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorPaul Eggert2022-09-09 15:22:16 -0500
committerPaul Eggert2022-09-09 16:19:49 -0500
commitfa993926181f8c607fbb1e86c3fe1f7e7bacf5e9 (patch)
treeab932ac50c73eb5511ca24eddf49645b56dc63bb /src/process.c
parent9189ad45612141cc9db5c3e98de5e44e07e6f9b0 (diff)
downloademacs-fa993926181f8c607fbb1e86c3fe1f7e7bacf5e9.tar.gz
emacs-fa993926181f8c607fbb1e86c3fe1f7e7bacf5e9.zip
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+.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c38
1 files 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)
7391} 7391}
7392 7392
7393/* LIB_CHILD_HANDLER is a SIGCHLD handler that Emacs calls while doing 7393/* LIB_CHILD_HANDLER is a SIGCHLD handler that Emacs calls while doing
7394 its own SIGCHLD handling. On POSIXish systems, glib needs this to 7394 its own SIGCHLD handling. On POSIXish systems lacking
7395 pidfd_open+waitid or using Glib 2.73.1-, Glib needs this to
7395 keep track of its own children. GNUstep is similar. */ 7396 keep track of its own children. GNUstep is similar. */
7396 7397
7397static void dummy_handler (int sig) {} 7398static void dummy_handler (int sig) {}
@@ -8358,7 +8359,7 @@ DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0,
8358 8359
8359#ifdef subprocesses 8360#ifdef subprocesses
8360/* Arrange to catch SIGCHLD if this hasn't already been arranged. 8361/* Arrange to catch SIGCHLD if this hasn't already been arranged.
8361 Invoke this after init_process_emacs, and after glib and/or GNUstep 8362 Invoke this after init_process_emacs, and after Glib and/or GNUstep
8362 futz with the SIGCHLD handler, but before Emacs forks any children. 8363 futz with the SIGCHLD handler, but before Emacs forks any children.
8363 This function's caller should block SIGCHLD. */ 8364 This function's caller should block SIGCHLD. */
8364 8365
@@ -8423,26 +8424,35 @@ init_process_emacs (int sockfd)
8423 if (!will_dump_with_unexec_p ()) 8424 if (!will_dump_with_unexec_p ())
8424 { 8425 {
8425#if defined HAVE_GLIB && !defined WINDOWSNT 8426#if defined HAVE_GLIB && !defined WINDOWSNT
8426 /* Tickle glib's child-handling code. Ask glib to install a 8427 /* Tickle Glib's child-handling code. Ask Glib to install a
8427 watch source for Emacs itself which will initialize glib's 8428 watch source for Emacs itself which will initialize glib's
8428 private SIGCHLD handler, allowing catch_child_signal to copy 8429 private SIGCHLD handler, allowing catch_child_signal to copy
8429 it into lib_child_handler. 8430 it into lib_child_handler. This is a hacky workaround to get
8431 glib's g_unix_signal_handler into lib_child_handler.
8430 8432
8431 Unfortunately in glib commit 2e471acf, the behavior changed to 8433 In Glib 2.37.5 (2013), commit 2e471acf changed Glib to
8432 always install a signal handler when g_child_watch_source_new 8434 always install a signal handler when g_child_watch_source_new
8433 is called and not just the first time it's called. Glib also 8435 is called and not just the first time it's called, and to
8434 now resets signal handlers to SIG_DFL when it no longer has a 8436 reset signal handlers to SIG_DFL when it no longer has a
8435 watcher on that signal. This is a hackey work around to get 8437 watcher on that signal. Arrange for Emacs's signal handler
8436 glib's g_unix_signal_handler into lib_child_handler. */ 8438 to be reinstalled even if this happens.
8439
8440 In Glib 2.73.2 (2022), commit f615eef4 changed Glib again,
8441 to not install a signal handler if the system supports
8442 pidfd_open and waitid (as in Linux kernel 5.3+). The hacky
8443 workaround is not needed in this case. */
8437 GSource *source = g_child_watch_source_new (getpid ()); 8444 GSource *source = g_child_watch_source_new (getpid ());
8438 catch_child_signal (); 8445 catch_child_signal ();
8439 g_source_unref (source); 8446 g_source_unref (source);
8440 8447
8441 eassert (lib_child_handler != dummy_handler); 8448 if (lib_child_handler != dummy_handler)
8442 signal_handler_t lib_child_handler_glib = lib_child_handler; 8449 {
8443 catch_child_signal (); 8450 /* The hacky workaround is needed on this platform. */
8444 eassert (lib_child_handler == dummy_handler); 8451 signal_handler_t lib_child_handler_glib = lib_child_handler;
8445 lib_child_handler = lib_child_handler_glib; 8452 catch_child_signal ();
8453 eassert (lib_child_handler == dummy_handler);
8454 lib_child_handler = lib_child_handler_glib;
8455 }
8446#else 8456#else
8447 catch_child_signal (); 8457 catch_child_signal ();
8448#endif 8458#endif