summaryrefslogtreecommitdiff
path: root/daemon/gdm-server.c
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@src.gnome.org>2007-05-14 20:50:58 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2007-05-14 20:50:58 +0000
commit300e005340dbc08a0509b7ec08dd5a2fba88489f (patch)
tree002bae3a8875cef05bdffa1695d6fcebe5c382ca /daemon/gdm-server.c
parent25854e3b29e066e916cf800b10f2f0aa449ac14d (diff)
downloadgdm-300e005340dbc08a0509b7ec08dd5a2fba88489f.tar.gz
Add some basic signal handling. Make sure we clean up child processes.
svn path=/branches/mccann-gobject/; revision=4931
Diffstat (limited to 'daemon/gdm-server.c')
-rw-r--r--daemon/gdm-server.c141
1 files changed, 102 insertions, 39 deletions
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 6f14737b..0d0eea7f 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -39,6 +39,7 @@
#include <X11/Xlib.h> /* for Display */
#include "gdm-common.h"
+#include "gdm-signal-handler.h"
#include "gdm-server.h"
@@ -103,58 +104,37 @@ static void gdm_server_finalize (GObject *object);
G_DEFINE_TYPE (GdmServer, gdm_server, G_TYPE_OBJECT)
-/* copied from nautilus */
-static int ready_pipes[2];
-
static gboolean
-ready_io_cb (GIOChannel *io,
- GIOCondition condition,
- GdmServer *server)
+emit_ready_idle (GdmServer *server)
{
- char a;
-
- while (read (ready_pipes[0], &a, 1) != 1)
- ;
-
g_debug ("Got USR1 from X server - emitting READY");
g_signal_emit (server, signals[READY], 0);
-
- return TRUE;
+ return FALSE;
}
-static void
-sigusr1_handler (int sig)
-{
- while (write (ready_pipes[1], "a", 1) != 1)
- ;
-}
-static void
-setup_ready_signal (GdmServer *server)
-{
- struct sigaction sa;
- GIOChannel *io;
-
- if (pipe (ready_pipes) == -1) {
- g_error ("Could not create pipe() for ready signal");
- }
+static gboolean
+signal_cb (int signo,
+ GdmServer *server)
- io = g_io_channel_unix_new (ready_pipes[0]);
- g_io_add_watch (io, G_IO_IN, (GIOFunc)ready_io_cb, server);
+{
+ g_idle_add ((GSourceFunc)emit_ready_idle, server);
- sa.sa_handler = sigusr1_handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction (SIGUSR1, &sa, NULL);
+ return TRUE;
}
-gboolean
-gdm_server_stop (GdmServer *server)
+static void
+setup_ready_signal (GdmServer *server)
{
- g_debug ("Stopping server");
-
- return TRUE;
+ GdmSignalHandler *signal_handler;
+
+ signal_handler = gdm_signal_handler_new ();
+ gdm_signal_handler_add (signal_handler,
+ SIGUSR1,
+ (GdmSignalHandlerFunc)signal_cb,
+ server);
+ g_object_unref (signal_handler);
}
/* We keep a connection (parent_dsp) open with the parent X server
@@ -647,6 +627,87 @@ gdm_server_start (GdmServer *server)
return res;
}
+static int
+signal_pid (int pid,
+ int signal)
+{
+ int status = -1;
+
+ /* perhaps block sigchld */
+
+ status = kill (pid, signal);
+
+ if (status < 0) {
+ if (errno == ESRCH) {
+ g_warning ("Child process %lu was already dead.",
+ (unsigned long) pid);
+ } else {
+ g_warning ("Couldn't kill child process %lu: %s",
+ (unsigned long) pid,
+ g_strerror (errno));
+ }
+ }
+
+ /* perhaps unblock sigchld */
+
+ return status;
+}
+
+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 ("waitpid () should not fail");
+ }
+ }
+
+ return status;
+}
+
+static void
+server_died (GdmServer *server)
+{
+ int exit_status;
+
+ g_debug ("Waiting on process %d", server->priv->pid);
+ exit_status = wait_on_child (server->priv->pid);
+
+ if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
+ g_debug ("Wait on child process failed");
+ } else {
+ /* exited normally */
+ }
+
+ g_spawn_close_pid (server->priv->pid);
+ server->priv->pid = -1;
+
+ g_debug ("Server died");
+}
+
+gboolean
+gdm_server_stop (GdmServer *server)
+{
+ if (server->priv->pid <= 1) {
+ return TRUE;
+ }
+
+ g_debug ("Stopping server");
+
+ signal_pid (server->priv->pid, SIGTERM);
+ server_died (server);
+
+ return TRUE;
+}
+
+
static void
_gdm_server_set_display_name (GdmServer *server,
const char *name)
@@ -768,6 +829,8 @@ gdm_server_finalize (GObject *object)
g_return_if_fail (server->priv != NULL);
+ gdm_server_stop (server);
+
G_OBJECT_CLASS (gdm_server_parent_class)->finalize (object);
}