diff options
author | robert.ancell@canonical.com <> | 2011-02-13 19:34:29 +1100 |
---|---|---|
committer | robert.ancell@canonical.com <> | 2011-02-13 19:34:29 +1100 |
commit | 4364040cb64ed332ff58a75a6e5419d1b29a39d0 (patch) | |
tree | aa30d1597828fcb6e42fdc3361d3d50b7912febf /src/xserver.c | |
parent | cd9bea22b437851c5eb56114c36e65d7956e3fac (diff) | |
download | lightdm-4364040cb64ed332ff58a75a6e5419d1b29a39d0.tar.gz |
Split child process code out from session/xserver
Diffstat (limited to 'src/xserver.c')
-rw-r--r-- | src/xserver.c | 176 |
1 files changed, 26 insertions, 150 deletions
diff --git a/src/xserver.c b/src/xserver.c index 328c8b24..71c48084 100644 --- a/src/xserver.c +++ b/src/xserver.c @@ -24,7 +24,6 @@ enum { READY, - EXITED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -39,9 +38,6 @@ struct XServerPrivate /* Path of file to log to */ gchar *log_file; - /* Environment variables */ - GHashTable *env; - /* Command to run the X server */ gchar *command; @@ -75,34 +71,14 @@ struct XServerPrivate /* Cached server address */ gchar *address; - /* X process */ - GPid pid; - /* Connection to X server */ xcb_connection_t *connection; }; -G_DEFINE_TYPE (XServer, xserver, G_TYPE_OBJECT); +G_DEFINE_TYPE (XServer, xserver, CHILD_PROCESS_TYPE); static GHashTable *servers = NULL; -void -xserver_handle_signal (GPid pid) -{ - XServer *server; - - server = g_hash_table_lookup (servers, GINT_TO_POINTER (pid)); - if (!server) - return; - - if (!server->priv->ready) - { - server->priv->ready = TRUE; - g_debug ("Got signal from X server :%d", server->priv->display_number); - g_signal_emit (server, signals[READY], 0); - } -} - XServer * xserver_new (XServerType type, const gchar *hostname, gint display_number) { @@ -148,12 +124,6 @@ xserver_get_log_file (XServer *server) } void -xserver_set_env (XServer *server, const gchar *name, const gchar *value) -{ - g_hash_table_insert (server->priv->env, g_strdup (name), g_strdup (value)); -} - -void xserver_set_port (XServer *server, guint port) { server->priv->port = port; @@ -294,88 +264,14 @@ xserver_connect (XServer *server) return xcb_connection_has_error (server->priv->connection) == 0; } -static void -xserver_watch_cb (GPid pid, gint status, gpointer data) -{ - XServer *server = data; - - if (WIFEXITED (status)) - g_debug ("XServer exited with return value %d", WEXITSTATUS (status)); - else if (WIFSIGNALED (status)) - g_debug ("XServer terminated with signal %d", WTERMSIG (status)); - - g_hash_table_remove (servers, GINT_TO_POINTER (server->priv->pid)); - - server->priv->pid = 0; - - g_signal_emit (server, signals[EXITED], 0); -} - -static void -xserver_fork_cb (gpointer data) -{ - XServer *server = data; - GHashTableIter iter; - gpointer key, value; - - /* Set environment */ - g_hash_table_iter_init (&iter, server->priv->env); - while (g_hash_table_iter_next (&iter, &key, &value)) - g_setenv ((gchar *)key, (gchar *)value, TRUE); - - /* Clear USR1 handler so the server will signal us when ready */ - signal (SIGUSR1, SIG_IGN); - - /* Redirect output to logfile */ - if (server->priv->log_file) - { - int fd; - - fd = g_open (server->priv->log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) - g_warning ("Failed to open session log file %s: %s", server->priv->log_file, g_strerror (errno)); - else - { - dup2 (fd, STDOUT_FILENO); - dup2 (fd, STDERR_FILENO); - close (fd); - } - } -} - -static gchar * -make_env_string (XServer *server) -{ - GString *string; - gchar *result; - gpointer key, value; - GHashTableIter iter; - - string = g_string_new (""); - g_hash_table_iter_init (&iter, server->priv->env); - if (g_hash_table_iter_next (&iter, &key, &value)) - { - g_string_append_printf (string, "%s=%s", (gchar *)key, (gchar *)value); - while (g_hash_table_iter_next (&iter, &key, &value)) - g_string_append_printf (string, " %s=%s", (gchar *)key, (gchar *)value); - } - result = string->str; - g_string_free (string, FALSE); - - return result; -} - gboolean xserver_start (XServer *server) { GError *error = NULL; gboolean result; GString *command; - gint argc; - gchar **argv, *env_string; - //gint xserver_stdin, xserver_stdout, xserver_stderr; - g_return_val_if_fail (server->priv->pid == 0, FALSE); + //g_return_val_if_fail (server->priv->pid == 0, FALSE); /* Check if we can connect to the remote server */ if (server->priv->type == XSERVER_TYPE_REMOTE) @@ -429,53 +325,34 @@ xserver_start (XServer *server) if (server->priv->vt >= 0) g_string_append_printf (command, " vt%d", server->priv->vt); - env_string = make_env_string (server); - g_debug ("Launching X Server: %s %s", env_string, command->str); - g_free (env_string); + g_debug ("Launching X Server"); - result = g_shell_parse_argv (command->str, &argc, &argv, &error); + result = child_process_start (CHILD_PROCESS (server), + NULL, /* Username (run as current user) */ + NULL, /* Environment (inherit parent) */ + command->str, + &error); g_string_free (command, TRUE); if (!result) - g_warning ("Failed to parse X server command line: %s", error->message); - g_clear_error (&error); - if (!result) - return FALSE; - - result = g_spawn_async (NULL, /* Working directory */ - argv, - NULL, - G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, - xserver_fork_cb, server, - &server->priv->pid, - &error); - g_strfreev (argv); - if (!result) g_warning ("Unable to create display: %s", error->message); else - { g_debug ("Waiting for signal from X server :%d", server->priv->display_number); - g_hash_table_insert (servers, GINT_TO_POINTER (server->priv->pid), server); - g_child_watch_add (server->priv->pid, xserver_watch_cb, server); - } g_clear_error (&error); - return server->priv->pid != 0; + return result; } void xserver_disconnect_clients (XServer *server) { server->priv->ready = FALSE; - - if (server->priv->pid) - kill (server->priv->pid, SIGHUP); + child_process_signal (CHILD_PROCESS (server), SIGHUP); } static void xserver_init (XServer *server) { server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, XSERVER_TYPE, XServerPrivate); - server->priv->env = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); server->priv->command = g_strdup (XSERVER_BINARY); server->priv->authentication_name = g_strdup (""); server->priv->vt = -1; @@ -488,16 +365,9 @@ xserver_finalize (GObject *object) self = XSERVER (object); - if (self->priv->pid > 0) - g_hash_table_remove (servers, GINT_TO_POINTER (self->priv->pid)); - if (self->priv->connection) xcb_disconnect (self->priv->connection); - - if (self->priv->pid) - kill (self->priv->pid, SIGTERM); - g_hash_table_unref (self->priv->env); g_free (self->priv->command); g_free (self->priv->hostname); g_free (self->priv->authentication_name); @@ -514,11 +384,26 @@ xserver_finalize (GObject *object) } static void +xserver_got_signal (ChildProcess *process, int signum) +{ + XServer *server = XSERVER (process); + + if (signum == SIGUSR1 && !server->priv->ready) + { + server->priv->ready = TRUE; + g_debug ("Got signal from X server :%d", server->priv->display_number); + g_signal_emit (server, signals[READY], 0); + } +} + +static void xserver_class_init (XServerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + ChildProcessClass *parent_class = CHILD_PROCESS_CLASS (klass); - object_class->finalize = xserver_finalize; + object_class->finalize = xserver_finalize; + parent_class->got_signal = xserver_got_signal; g_type_class_add_private (klass, sizeof (XServerPrivate)); @@ -531,14 +416,5 @@ xserver_class_init (XServerClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - signals[EXITED] = - g_signal_new ("exited", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XServerClass, exited), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - servers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); } |