[gdm/wip/wayland-rebase: 6/15] signals



commit a93297944d47eee122ed32bf80c40ea160b78622
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Feb 14 14:32:50 2014 -0500

    signals

 daemon/gdm-server.c |   75 +++++++++++++++++++++++++++++++++++++++++---------
 daemon/main.c       |   26 ++++++++++-------
 2 files changed, 76 insertions(+), 25 deletions(-)
---
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 1606b3a..c9de12d 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -94,7 +94,6 @@ struct GdmServerPrivate
         char    *auth_file;
 
         guint    child_watch_id;
-        guint    sigusr1_id;
 
         gboolean is_initial;
 };
@@ -180,16 +179,66 @@ gdm_server_get_display_device (GdmServer *server)
         return g_strdup (server->priv->display_device);
 }
 
+static void
+gdm_server_ready (GdmServer *server)
+{
+        g_debug ("GdmServer: Got USR1 from X server - emitting READY");
+        g_signal_emit (server, signals[READY], 0);
+}
+
+static GSList *active_servers;
+
 static gboolean
-on_sigusr1 (gpointer user_data)
+got_sigusr1 (gpointer user_data)
+{
+        GPid pid = GPOINTER_TO_UINT (user_data);
+        GSList *l;
+
+        for (l = active_servers; l; l = l->next) {
+                GdmServer *server = l->data;
 
+                if (server->priv->pid == pid)
+                        gdm_server_ready (server);
+        }
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+sigusr1_thread_on_sigusr1 (int        signo,
+                           siginfo_t *siginfo,
+                           void      *context)
 {
-        GdmServer *server = user_data;
+        g_idle_add (got_sigusr1, GUINT_TO_POINTER (siginfo->si_pid));
+}
 
-        g_debug ("GdmServer: Got USR1 from X server - emitting READY");
+static gpointer
+sigusr1_thread_main (gpointer user_data)
+{
+        sigset_t mask;
+        struct sigaction sigusr1_handler;
 
-        g_signal_emit (server, signals[READY], 0);
-        return FALSE;
+        /* Handle only SIGUSR1 */
+        sigemptyset (&mask);
+        sigaddset (&mask, SIGUSR1);
+        sigprocmask (SIG_SETMASK, &mask, NULL);
+
+        /* Set up our SIGUSR1 handler */
+        sigusr1_handler.sa_sigaction = sigusr1_thread_on_sigusr1;
+        sigusr1_handler.sa_flags = SA_SIGINFO | SA_RESTART;
+        sigaction (SIGUSR1, &sigusr1_handler, NULL);
+
+        return NULL;
+}
+
+static void
+gdm_server_launch_sigusr1_thread_if_needed (void)
+{
+        static GThread *sigusr1_thread;
+
+        if (sigusr1_thread == NULL) {
+                sigusr1_thread = g_thread_new ("gdm SIGUSR1 catcher", sigusr1_thread_main, NULL);
+        }
 }
 
 /* We keep a connection (parent_dsp) open with the parent X server
@@ -676,6 +725,8 @@ server_child_watch (GPid       pid,
                 g_signal_emit (server, signals [DIED], 0, num);
         }
 
+        active_servers = g_slist_remove (active_servers, server);
+
         g_spawn_close_pid (server->priv->pid);
         server->priv->pid = -1;
 
@@ -719,6 +770,10 @@ gdm_server_spawn (GdmServer    *server,
         g_debug ("GdmServer: Starting X server process: %s", freeme);
         g_free (freeme);
 
+        active_servers = g_slist_append (active_servers, server);
+
+        gdm_server_launch_sigusr1_thread_if_needed ();
+
         if (!g_spawn_async_with_pipes (NULL,
                                        argv,
                                        (char **)env->pdata,
@@ -1063,16 +1118,11 @@ gdm_server_class_init (GdmServerClass *klass)
 static void
 gdm_server_init (GdmServer *server)
 {
-
         server->priv = GDM_SERVER_GET_PRIVATE (server);
 
         server->priv->pid = -1;
 
         server->priv->log_dir = g_strdup (LOGDIR);
-
-        server->priv->sigusr1_id = g_unix_signal_add (SIGUSR1,
-                                                      on_sigusr1,
-                                                      server);
 }
 
 static void
@@ -1087,9 +1137,6 @@ gdm_server_finalize (GObject *object)
 
         g_return_if_fail (server->priv != NULL);
 
-        if (server->priv->sigusr1_id > 0)
-                g_source_remove (server->priv->sigusr1_id);
-
         gdm_server_stop (server);
 
         g_free (server->priv->command);
diff --git a/daemon/main.c b/daemon/main.c
index b95802f..cdb41fa 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -288,16 +288,6 @@ on_sighup_cb (gpointer user_data)
 }
 
 static gboolean
-on_sigusr1_cb (gpointer user_data)
-{
-        g_debug ("Got USR1 signal");
-
-        gdm_log_toggle_debug ();
-
-        return TRUE;
-}
-
-static gboolean
 is_debug_set (void)
 {
         gboolean debug;
@@ -305,6 +295,19 @@ is_debug_set (void)
         return debug;
 }
 
+/* SIGUSR1 is used by the X server to tell us that we're ready, so
+ * block it. We'll unblock it in the worker thread in gdm-server.c
+ */
+static void
+block_sigusr1 (void)
+{
+        sigset_t mask;
+
+        sigemptyset (&mask);
+        sigaddset (&mask, SIGUSR1);
+        sigprocmask (SIG_BLOCK, &mask, NULL);
+}
+
 int
 main (int    argc,
       char **argv)
@@ -325,6 +328,8 @@ main (int    argc,
                 { NULL }
         };
 
+        block_sigusr1 ();
+
         bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
         textdomain (GETTEXT_PACKAGE);
         setlocale (LC_ALL, "");
@@ -400,7 +405,6 @@ main (int    argc,
         g_unix_signal_add (SIGTERM, on_shutdown_signal_cb, main_loop);
         g_unix_signal_add (SIGINT, on_shutdown_signal_cb, main_loop);
         g_unix_signal_add (SIGHUP, on_sighup_cb, NULL);
-        g_unix_signal_add (SIGUSR1, on_sigusr1_cb, NULL);
 
         if (do_timed_exit) {
                 g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, main_loop);


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