Subject: bug#14474: 24.3.50; Zombie subprocesses (again)

From: Paul Eggert <[email-masked]>
Date: Sun, 26 May 2013 18:36:15 -0700

[The bug is that a bleeding-edge GTK Emacs loses child processes
when it's run via sudo; see <http://bugs.gnu.org/14474>.]

I think I may have spotted the problem.
Glib 2.36.2's glib/gmain.c has a function
'ensure_unix_signal_handler_installed_unlocked'
that is run in the dconf worker thread.
This function calls sigaction to replace Emacs's SIGCHLD handler
with glib's own handler g_unix_signal_handler.
Signal handlers are process-wide, so this replacement affects
all threads, including the main (Emacs) thread.

After that happens, Emacs never sees when its children
exit, since g_unix_signal_handler discards Emacs's
child-exit notices, and the Emacs function
deliver_child_signal is never invoked.

The comment for g_child_watch_source_new
says that Emacs isn't supposed to invoke waitpid (-1, ...),
but that's already the case in the Emacs trunk.
Is there another limitation that we
didn't know about, a limitation that says Emacs can't
have signal handlers either?

I'll CC: this to Colin Walters since he seemed to have
a good handle on the situation from the glib point of view; see
<https://bugzilla.gnome.org/show_bug.cgi?id=676167>.

One possibility is to see if we can get Emacs to use
glib's child watcher.  But that's a bit of a delicate balance,
since Emacs must work even when gtk is absent, and it may need
to hand off from its own watcher to glib's watcher, and processes
shouldn't get lost during the handoff.  I don't offhand know how
to do all that.

A simpler but hacky workaround is to not use the graphical interface if
DBUS_SESSION_BUS_ADDRESS is unset.  Something like this:

--- src/xterm.c	2013-05-09 14:49:56 +0000
+++ src/xterm.c	2013-05-27 01:32:44 +0000
@@ -9819,6 +9819,14 @@ x_display_ok (const char *display)
     int dpy_ok = 1;
     Display *dpy;
 
+#ifdef USE_GTK
+    if (! egetenv ("DBUS_SESSION_BUS_ADDRESS"))
+      {
+	fprintf (stderr, "DBUS_SESSION_BUS_ADDRESS unset, so Gtk is unsafe\n");
+	return 0;
+      }
+#endif
+
     dpy = XOpenDisplay (display);
     if (dpy)
       XCloseDisplay (dpy);