[gnome-settings-daemon] mouse: Stop syndaemon when settings-daemon dies



commit 31aa30a0207b9de77706f03dacb8d914c959d3a6
Author: Martin Pitt <martin pitt ubuntu com>
Date:   Wed Mar 14 11:11:18 2012 +0100

    mouse: Stop syndaemon when settings-daemon dies
    
    Ensure that a spawned syndaemon gets killed when settings-daemon exists due to
    a crash, a keyboard interrupt, etc. This avoids having multiple syndaemons run
    at the same time, which can lead to the trackpad malfunctioning.
    
    This uses prctl(PR_SET_PDEATHSIG), so only works on Linux.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=668667

 plugins/mouse/gsd-mouse-manager.c |   32 +++++++++++++++++++++++++++++++-
 1 files changed, 31 insertions(+), 1 deletions(-)
---
diff --git a/plugins/mouse/gsd-mouse-manager.c b/plugins/mouse/gsd-mouse-manager.c
index e8a4787..9af0553 100644
--- a/plugins/mouse/gsd-mouse-manager.c
+++ b/plugins/mouse/gsd-mouse-manager.c
@@ -28,6 +28,9 @@
 #include <string.h>
 #include <errno.h>
 #include <math.h>
+#ifdef __linux
+#include <sys/prctl.h>
+#endif
 
 #include <locale.h>
 
@@ -502,6 +505,26 @@ set_middle_button (GsdMouseManager *manager,
         XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
 }
 
+/* Ensure that syndaemon dies together with us, to avoid running several of
+ * them */
+static void
+setup_syndaemon (gpointer user_data)
+{
+#ifdef __linux
+        prctl (PR_SET_PDEATHSIG, SIGHUP);
+#endif
+}
+
+static void
+syndaemon_died (GPid pid, gint status, gpointer user_data)
+{
+        GsdMouseManager *manager = GSD_MOUSE_MANAGER (user_data);
+
+        g_debug ("syndaemon stopped with status %i", status);
+        g_spawn_close_pid (pid);
+        manager->priv->syndaemon_spawned = FALSE;
+}
+
 static int
 set_disable_w_typing (GsdMouseManager *manager, gboolean state)
 {
@@ -522,15 +545,22 @@ set_disable_w_typing (GsdMouseManager *manager, gboolean state)
                 if (!g_find_program_in_path (args[0]))
                         return 0;
 
+                /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid
+                 * double-forking, otherwise syndaemon will immediately get
+                 * killed again through (PR_SET_PDEATHSIG when the intermediate
+                 * process dies */
                 g_spawn_async (g_get_home_dir (), args, NULL,
-                                G_SPAWN_SEARCH_PATH, NULL, NULL,
+                                G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL,
                                 &manager->priv->syndaemon_pid, &error);
 
                 manager->priv->syndaemon_spawned = (error == NULL);
 
                 if (error) {
+                        g_warning ("Failed to launch syndaemon: %s", error->message);
                         g_settings_set_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING, FALSE);
                         g_error_free (error);
+                } else {
+                        g_child_watch_add (manager->priv->syndaemon_pid, syndaemon_died, manager);
                 }
         } else if (manager->priv->syndaemon_spawned) {
                 kill (manager->priv->syndaemon_pid, SIGHUP);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]