diff options
author | William Jon McCann <jmccann@redhat.com> | 2008-03-04 20:49:07 +0000 |
---|---|---|
committer | William Jon McCann <mccann@src.gnome.org> | 2008-03-04 20:49:07 +0000 |
commit | d9503b6b2b4da2c2aad691715aa8169ce65b7040 (patch) | |
tree | 188d7f8485b00f260cdc59c31f3a1d1a22d384ee | |
parent | c6e462b746695efdd4d60fd55db517ad2db4a8ce (diff) | |
download | gdm-d9503b6b2b4da2c2aad691715aa8169ce65b7040.tar.gz |
Destroy the remote login window when the xserver quits.
2008-03-04 William Jon McCann <jmccann@redhat.com>
* gui/simple-greeter/gdm-remote-login-window.c: (wait_on_child),
(xserver_died), (stop_xserver), (xserver_child_watch),
(start_xephyr):
* gui/simple-greeter/gdm-session-client.c: (wait_on_child),
(gdm_session_client_dispose):
* gui/simple-greeter/test-remote-login-window.c: (main):
Destroy the remote login window when the xserver quits.
svn path=/trunk/; revision=5923
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-remote-login-window.c | 152 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-session-client.c | 4 | ||||
-rw-r--r-- | gui/simple-greeter/test-remote-login-window.c | 1 |
4 files changed, 150 insertions, 17 deletions
@@ -1,5 +1,15 @@ 2008-03-04 William Jon McCann <jmccann@redhat.com> + * gui/simple-greeter/gdm-remote-login-window.c: (wait_on_child), + (xserver_died), (stop_xserver), (xserver_child_watch), + (start_xephyr): + * gui/simple-greeter/gdm-session-client.c: (wait_on_child), + (gdm_session_client_dispose): + * gui/simple-greeter/test-remote-login-window.c: (main): + Destroy the remote login window when the xserver quits. + +2008-03-04 William Jon McCann <jmccann@redhat.com> + * gui/simple-chooser/Makefile.am: * gui/simple-chooser/gdm-chooser-host.c: (gdm_chooser_host_get_address), (gdm_chooser_host_get_description), diff --git a/gui/simple-greeter/gdm-remote-login-window.c b/gui/simple-greeter/gdm-remote-login-window.c index 450cc26b..c6f48b25 100644 --- a/gui/simple-greeter/gdm-remote-login-window.c +++ b/gui/simple-greeter/gdm-remote-login-window.c @@ -23,6 +23,9 @@ #include <stdlib.h> #include <stdio.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> #include <glib.h> #include <glib/gi18n.h> @@ -33,6 +36,7 @@ #include <gtk/gtk.h> #include "gdm-remote-login-window.h" +#include "gdm-common.h" #define GDM_REMOTE_LOGIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_REMOTE_LOGIN_WINDOW, GdmRemoteLoginWindowPrivate)) @@ -41,6 +45,8 @@ struct GdmRemoteLoginWindowPrivate gboolean connected; char *hostname; char *display; + GPid xserver_pid; + guint xserver_watch_id; }; enum { @@ -60,31 +66,145 @@ static void gdm_remote_login_window_finalize (GObject G_DEFINE_TYPE (GdmRemoteLoginWindow, gdm_remote_login_window, GTK_TYPE_WINDOW) +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 ("GdmRemoteLoginWindow: waitpid () should not fail"); + } + } + + return status; +} + +static void +xserver_died (GdmRemoteLoginWindow *login_window) +{ + int exit_status; + + g_debug ("GdmRemoteLoginWindow: Waiting on process %d", login_window->priv->xserver_pid); + exit_status = wait_on_child (login_window->priv->xserver_pid); + + if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) { + g_debug ("GdmRemoteLoginWindow: Wait on child process failed"); + } else { + /* exited normally */ + } + + g_spawn_close_pid (login_window->priv->xserver_pid); + login_window->priv->xserver_pid = -1; + + g_debug ("GdmRemoteLoginWindow: xserver died"); +} + +static void +stop_xserver (GdmRemoteLoginWindow *login_window) +{ + /* remove watch before killing so we don't restart */ + if (login_window->priv->xserver_watch_id > 0) { + g_source_remove (login_window->priv->xserver_watch_id); + login_window->priv->xserver_watch_id = 0; + } + + g_debug ("GdmRemoteLoginWindow: Stopping xserver"); + if (login_window->priv->xserver_pid > 0) { + gdm_signal_pid (login_window->priv->xserver_pid, SIGTERM); + xserver_died (login_window); + } +} + +static void +xserver_child_watch (GPid pid, + int status, + GdmRemoteLoginWindow *login_window) +{ + g_debug ("GdmRemoteLoginWindow: **** xserver (pid:%d) done (%s:%d)", + (int) pid, + WIFEXITED (status) ? "status" + : WIFSIGNALED (status) ? "signal" + : "unknown", + WIFEXITED (status) ? WEXITSTATUS (status) + : WIFSIGNALED (status) ? WTERMSIG (status) + : -1); + + g_spawn_close_pid (login_window->priv->xserver_pid); + + login_window->priv->xserver_pid = -1; + login_window->priv->xserver_watch_id = 0; + + gtk_widget_destroy (GTK_WIDGET (login_window)); +} + static gboolean start_xephyr (GdmRemoteLoginWindow *login_window) { - char *cmd; - gboolean res; - GError *error; - - cmd = g_strdup_printf ("Xephyr -query %s -parent 0x%x -br -once %s", - login_window->priv->hostname, - (unsigned int)GDK_WINDOW_XID (GTK_WIDGET (login_window)->window), - login_window->priv->display); - g_debug ("Running: %s", cmd); + GError *local_error; + char **argv; + gboolean res; + gboolean ret; + int flags; + char *command; + + command = g_strdup_printf ("Xephyr -query %s -parent 0x%x -br -once %s", + login_window->priv->hostname, + (unsigned int)GDK_WINDOW_XID (GTK_WIDGET (login_window)->window), + login_window->priv->display); + g_debug ("GdmRemoteLoginWindow: Running: %s", command); + + ret = FALSE; + + argv = NULL; + local_error = NULL; + res = g_shell_parse_argv (command, NULL, &argv, &local_error); + if (! res) { + g_warning ("GdmRemoteLoginWindow: Unable to parse command: %s", local_error->message); + g_error_free (local_error); + goto out; + } - error = NULL; - res = g_spawn_command_line_async (cmd, &error); + flags = G_SPAWN_SEARCH_PATH + | G_SPAWN_DO_NOT_REAP_CHILD; - g_free (cmd); + local_error = NULL; + res = g_spawn_async (NULL, + argv, + NULL, + flags, + NULL, + NULL, + &login_window->priv->xserver_pid, + &local_error); + g_strfreev (argv); if (! res) { - g_warning ("Could not start nested X server: %s", error->message); - g_error_free (error); - return FALSE; + g_warning ("GdmRemoteLoginWindow: Unable to run command %s: %s", + command, + local_error->message); + g_error_free (local_error); + goto out; } - return TRUE; + g_debug ("GdmRemoteLoginWindow: Started: pid=%d command='%s'", + login_window->priv->xserver_pid, + command); + + login_window->priv->xserver_watch_id = g_child_watch_add (login_window->priv->xserver_pid, + (GChildWatchFunc)xserver_child_watch, + login_window); + ret = TRUE; + + out: + g_free (command); + + return ret; } static gboolean diff --git a/gui/simple-greeter/gdm-session-client.c b/gui/simple-greeter/gdm-session-client.c index 1b75ffac..12b368df 100644 --- a/gui/simple-greeter/gdm-session-client.c +++ b/gui/simple-greeter/gdm-session-client.c @@ -174,7 +174,7 @@ wait_on_child (int pid) } else if (errno == ECHILD) { ; /* do nothing, child already reaped */ } else { - g_debug ("GdmWelcomeSession: waitpid () should not fail"); + g_debug ("GdmSessionClient: waitpid () should not fail"); } } @@ -418,6 +418,8 @@ gdm_session_client_constructor (GType type, static void gdm_session_client_dispose (GObject *object) { + gdm_session_client_stop (GDM_SESSION_CLIENT (object)); + G_OBJECT_CLASS (gdm_session_client_parent_class)->dispose (object); } diff --git a/gui/simple-greeter/test-remote-login-window.c b/gui/simple-greeter/test-remote-login-window.c index 8bf1e739..5a3bd1c1 100644 --- a/gui/simple-greeter/test-remote-login-window.c +++ b/gui/simple-greeter/test-remote-login-window.c @@ -79,6 +79,7 @@ main (int argc, char *argv[]) gtk_init (&argc, &argv); login_window = gdm_remote_login_window_new (TRUE); + g_signal_connect (login_window, "destroy", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show (login_window); gdm_remote_login_window_connect (GDM_REMOTE_LOGIN_WINDOW (login_window), hostname); |