summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Jon McCann <jmccann@redhat.com>2008-03-04 20:49:07 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2008-03-04 20:49:07 +0000
commitd9503b6b2b4da2c2aad691715aa8169ce65b7040 (patch)
tree188d7f8485b00f260cdc59c31f3a1d1a22d384ee
parentc6e462b746695efdd4d60fd55db517ad2db4a8ce (diff)
downloadgdm-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--ChangeLog10
-rw-r--r--gui/simple-greeter/gdm-remote-login-window.c152
-rw-r--r--gui/simple-greeter/gdm-session-client.c4
-rw-r--r--gui/simple-greeter/test-remote-login-window.c1
4 files changed, 150 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 4d13e4f0..3f1599bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);