gdm r5790 - in trunk: . gui/simple-greeter



Author: mccann
Date: Mon Feb 18 20:12:21 2008
New Revision: 5790
URL: http://svn.gnome.org/viewvc/gdm?rev=5790&view=rev

Log:
2008-02-18  William Jon McCann  <jmccann redhat com>

	* gui/simple-greeter/gdm-session-client.c: (client_child_watch),
	(gdm_session_client_start), (wait_on_child), (client_died),
	(gdm_session_client_stop), (gdm_session_client_class_init):
	* gui/simple-greeter/gdm-session-client.h:
	Watch session client processes.



Modified:
   trunk/ChangeLog
   trunk/gui/simple-greeter/gdm-session-client.c
   trunk/gui/simple-greeter/gdm-session-client.h

Modified: trunk/gui/simple-greeter/gdm-session-client.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-session-client.c	(original)
+++ trunk/gui/simple-greeter/gdm-session-client.c	Mon Feb 18 20:12:21 2008
@@ -44,6 +44,7 @@
         char    *try_exec;
         gboolean enabled;
         GPid     pid;
+        guint    child_watch_id;
 };
 
 enum {
@@ -52,12 +53,49 @@
         PROP_ENABLED,
 };
 
+enum {
+        EXITED,
+        DIED,
+        LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
 static void     gdm_session_client_class_init  (GdmSessionClientClass *klass);
 static void     gdm_session_client_init        (GdmSessionClient      *session_client);
 static void     gdm_session_client_finalize    (GObject               *object);
 
 G_DEFINE_TYPE (GdmSessionClient, gdm_session_client, G_TYPE_OBJECT)
 
+static void
+client_child_watch (GPid              pid,
+                    int               status,
+                    GdmSessionClient *client)
+{
+        g_debug ("GdmSessionClient: **** child '%s' (pid:%d) done (%s:%d)",
+                 client->priv->name,
+                 (int) pid,
+                 WIFEXITED (status) ? "status"
+                 : WIFSIGNALED (status) ? "signal"
+                 : "unknown",
+                 WIFEXITED (status) ? WEXITSTATUS (status)
+                 : WIFSIGNALED (status) ? WTERMSIG (status)
+                 : -1);
+
+        if (WIFEXITED (status)) {
+                int code = WEXITSTATUS (status);
+                g_signal_emit (client, signals [EXITED], 0, code);
+        } else if (WIFSIGNALED (status)) {
+                int num = WTERMSIG (status);
+                g_signal_emit (client, signals [DIED], 0, num);
+        }
+
+        g_spawn_close_pid (client->priv->pid);
+
+        client->priv->pid = -1;
+        client->priv->child_watch_id = 0;
+}
+
 gboolean
 gdm_session_client_start (GdmSessionClient *client,
                           GError          **error)
@@ -77,7 +115,7 @@
         local_error = NULL;
         res = g_shell_parse_argv (client->priv->command, NULL, &argv, &local_error);
         if (! res) {
-                g_warning ("Unable to parse command: %s", local_error->message);
+                g_warning ("GdmSessionClient: Unable to parse command: %s", local_error->message);
                 g_propagate_error (error, local_error);
                 goto out;
         }
@@ -87,6 +125,7 @@
                              argv,
                              NULL,
                              G_SPAWN_SEARCH_PATH
+                             | G_SPAWN_DO_NOT_REAP_CHILD
                              | G_SPAWN_STDOUT_TO_DEV_NULL
                              | G_SPAWN_STDERR_TO_DEV_NULL,
                              NULL,
@@ -96,28 +135,79 @@
         g_strfreev (argv);
 
         if (! res) {
-                g_warning ("Unable to run command %s: %s",
+                g_warning ("GdmSessionClient: Unable to run command %s: %s",
                            client->priv->command,
                            local_error->message);
                 g_propagate_error (error, local_error);
                 goto out;
         }
 
+        g_debug ("GdmSessionClient: Started: pid=%d command='%s'", client->priv->pid, client->priv->command);
+
+        client->priv->child_watch_id = g_child_watch_add (client->priv->pid,
+                                                          (GChildWatchFunc)client_child_watch,
+                                                          client);
+
         ret = TRUE;
 
  out:
         return ret;
 }
 
+static int
+wait_on_child (int pid)
+{
+        int status;
+
+ wait_again:
+        if (waitpid (pid, &status, 0) < 0) {
+                if (errno == EINTR) {
+                        goto wait_again;
+                } else if (errno == ECHILD) {
+                        ; /* do nothing, child already reaped */
+                } else {
+                        g_debug ("GdmWelcomeSession: waitpid () should not fail");
+                }
+        }
+
+        return status;
+}
+
+static void
+client_died (GdmSessionClient *client)
+{
+        int exit_status;
+
+        g_debug ("GdmSessionClient: Waiting on process %d", client->priv->pid);
+        exit_status = wait_on_child (client->priv->pid);
+
+        if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
+                g_debug ("GdmSessionClient: Wait on child process failed");
+        } else {
+                /* exited normally */
+        }
+
+        g_spawn_close_pid (client->priv->pid);
+        client->priv->pid = -1;
+
+        g_debug ("GdmSessionClient: SessionClient died");
+}
+
 void
 gdm_session_client_stop (GdmSessionClient *client)
 {
         g_return_if_fail (GDM_IS_SESSION_CLIENT (client));
 
+        /* remove watch before killing so we don't restart */
+        if (client->priv->child_watch_id > 0) {
+                g_source_remove (client->priv->child_watch_id);
+                client->priv->child_watch_id = 0;
+        }
+
         g_debug ("GdmSessionClient: Stopping client: %s", client->priv->name);
         if (client->priv->pid > 0) {
                 gdm_signal_pid (client->priv->pid, SIGTERM);
-                client->priv->pid = 0;
+                client_died (client);
         }
 }
 
@@ -356,6 +446,29 @@
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
+        signals [EXITED] =
+                g_signal_new ("exited",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmSessionClientClass, exited),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__INT,
+                              G_TYPE_NONE,
+                              1,
+                              G_TYPE_INT);
+        signals [DIED] =
+                g_signal_new ("died",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmSessionClientClass, died),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__INT,
+                              G_TYPE_NONE,
+                              1,
+                              G_TYPE_INT);
+
         g_type_class_add_private (klass, sizeof (GdmSessionClientPrivate));
 }
 

Modified: trunk/gui/simple-greeter/gdm-session-client.h
==============================================================================
--- trunk/gui/simple-greeter/gdm-session-client.h	(original)
+++ trunk/gui/simple-greeter/gdm-session-client.h	Mon Feb 18 20:12:21 2008
@@ -43,6 +43,11 @@
 typedef struct
 {
         GObjectClass   parent_class;
+
+        void (* exited)            (GdmSessionClient  *client,
+                                    int                exit_code);
+        void (* died)              (GdmSessionClient  *client,
+                                    int                signal_number);
 } GdmSessionClientClass;
 
 GType                  gdm_session_client_get_type              (void);



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