[gnome-session] gsm: Make it possible for a .session file to define a fallback session
- From: Vincent Untz <vuntz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-session] gsm: Make it possible for a .session file to define a fallback session
- Date: Mon, 29 Nov 2010 19:09:45 +0000 (UTC)
commit 8e6713f15a2819dd7bdd8a9a33ec2314633ff2d6
Author: Vincent Untz <vuntz gnome org>
Date: Mon Nov 29 19:28:07 2010 +0100
gsm: Make it possible for a .session file to define a fallback session
Two new keys are introduced: IsRunnableHelper and FallbackSession.
The first one defines a helper that is run to know if the session can be
used (only if the helper returns 0). The second defines the fallback
session to use if the helper doesn't return 0.
The helper cannot run for more than 500 ms.
There is a test program to make sure that our helper process management
works okay.
gnome-session/Makefile.am | 8 ++-
gnome-session/gsm-process-helper.c | 142 +++++++++++++++++++++++++++++++++++
gnome-session/gsm-process-helper.h | 33 ++++++++
gnome-session/gsm-session-fill.c | 49 ++++++++++++-
gnome-session/test-process-helper.c | 58 ++++++++++++++
5 files changed, 288 insertions(+), 2 deletions(-)
---
diff --git a/gnome-session/Makefile.am b/gnome-session/Makefile.am
index f25c4b7..030052e 100644
--- a/gnome-session/Makefile.am
+++ b/gnome-session/Makefile.am
@@ -2,7 +2,8 @@ bin_PROGRAMS = gnome-session
noinst_LTLIBRARIES = libgsmutil.la
noinst_PROGRAMS = \
test-client-dbus \
- test-inhibit
+ test-inhibit \
+ test-process-helper
AM_CPPFLAGS = \
$(GNOME_SESSION_CFLAGS) \
@@ -48,6 +49,8 @@ gnome_session_SOURCES = \
gsm-inhibitor.c \
gsm-manager.c \
gsm-manager.h \
+ gsm-process-helper.c \
+ gsm-process-helper.h \
gsm-session-fill.c \
gsm-session-fill.h \
gsm-session-save.c \
@@ -95,6 +98,9 @@ test_inhibit_LDADD = $(GNOME_SESSION_LIBS)
test_client_dbus_SOURCES = test-client-dbus.c
test_client_dbus_LDADD = $(DBUS_GLIB_LIBS)
+test_process_helper_SOURCES = test-process-helper.c gsm-process-helper.c gsm-process-helper.h
+test_process_helper_LDADD = $(DBUS_GLIB_LIBS)
+
gsm-marshal.c: gsm-marshal.list
$(AM_V_GEN)echo "#include \"gsm-marshal.h\"" > $@ && \
$(GLIB_GENMARSHAL) $< --prefix=gsm_marshal --body >> $@
diff --git a/gnome-session/gsm-process-helper.c b/gnome-session/gsm-process-helper.c
new file mode 100644
index 0000000..c36fe2a
--- /dev/null
+++ b/gnome-session/gsm-process-helper.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <glib.h>
+
+#include "gsm-process-helper.h"
+
+typedef struct {
+ const char *command_line;
+ GPid pid;
+ gboolean proper_exit;
+ int status;
+ GMainLoop *loop;
+ guint child_id;
+ guint timeout_id;
+} GsmProcessHelper;
+
+static void
+on_child_exited_simple (GPid pid,
+ gint status,
+ gpointer data)
+{
+ g_spawn_close_pid (pid);
+}
+
+static void
+on_child_exited (GPid pid,
+ gint status,
+ gpointer data)
+{
+ GsmProcessHelper *helper = data;
+
+ helper->proper_exit = TRUE;
+ helper->status = status;
+
+ g_spawn_close_pid (pid);
+ g_main_loop_quit (helper->loop);
+}
+
+static gboolean
+on_child_timeout (gpointer data)
+{
+ GsmProcessHelper *helper = data;
+
+ kill (helper->pid, SIGTERM);
+ g_warning ("Had to kill '%s' helper", helper->command_line);
+
+ helper->proper_exit = FALSE;
+ g_main_loop_quit (helper->loop);
+
+ return FALSE;
+}
+
+int
+gsm_process_helper (const char *command_line,
+ unsigned int timeout)
+{
+ GsmProcessHelper *helper;
+ gchar **argv = NULL;
+ GPid pid;
+ gboolean ret;
+ int exit_status = -1;
+
+ if (!g_shell_parse_argv (command_line, NULL, &argv, NULL))
+ return -1;
+
+ ret = g_spawn_async (NULL,
+ argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL,
+ NULL,
+ &pid,
+ NULL);
+
+ g_strfreev (argv);
+
+ if (!ret)
+ return -1;
+
+ helper = g_slice_new0 (GsmProcessHelper);
+
+ helper->command_line = command_line;
+ helper->pid = pid;
+ helper->proper_exit = FALSE;
+ helper->status = -1;
+
+ helper->loop = g_main_loop_new (NULL, FALSE);
+ helper->child_id = g_child_watch_add (helper->pid, on_child_exited, helper);
+ helper->timeout_id = g_timeout_add (timeout, on_child_timeout, helper);
+
+ g_main_loop_run (helper->loop);
+
+ if (helper->proper_exit && WIFEXITED (helper->status))
+ exit_status = WEXITSTATUS (helper->status);
+ else if (!helper->proper_exit) {
+ /* we'll need to call g_spawn_close_pid when the helper exits */
+ g_child_watch_add (pid, on_child_exited_simple, NULL);
+ }
+
+ if (helper->loop) {
+ g_main_loop_unref (helper->loop);
+ helper->loop = NULL;
+ }
+
+ if (helper->child_id) {
+ g_source_remove (helper->child_id);
+ helper->child_id = 0;
+ }
+
+ if (helper->timeout_id) {
+ g_source_remove (helper->timeout_id);
+ helper->timeout_id = 0;
+ }
+
+ g_slice_free (GsmProcessHelper, helper);
+
+ return exit_status;
+}
diff --git a/gnome-session/gsm-process-helper.h b/gnome-session/gsm-process-helper.h
new file mode 100644
index 0000000..f7aa18c
--- /dev/null
+++ b/gnome-session/gsm-process-helper.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GSM_PROCESS_HELPER_H
+#define __GSM_PROCESS_HELPER_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+int gsm_process_helper (const char *command_line,
+ unsigned int timeout);
+
+G_END_DECLS
+
+#endif /* __GSM_PROCESS_HELPER_H */
diff --git a/gnome-session/gsm-session-fill.c b/gnome-session/gsm-session-fill.c
index 12825cd..c7ee61f 100644
--- a/gnome-session/gsm-session-fill.c
+++ b/gnome-session/gsm-session-fill.c
@@ -25,14 +25,19 @@
#include "gsm-consolekit.h"
#include "gsm-manager.h"
+#include "gsm-process-helper.h"
#include "gsm-util.h"
#define GSM_DEFAULT_SESSION "gnome"
#define GSM_KEYFILE_SESSION_GROUP "GNOME Session"
+#define GSM_KEYFILE_RUNNABLE_KEY "IsRunnableHelper"
+#define GSM_KEYFILE_FALLBACK_KEY "FallbackSession"
#define GSM_KEYFILE_REQUIRED_KEY "Required"
#define GSM_KEYFILE_DEFAULT_KEY "DefaultApps"
+#define GSM_RUNNABLE_HELPER_TIMEOUT 500 /* ms */
+
/* This doesn't contain the required components, so we need to always
* call append_required_apps() after a call to append_default_apps(). */
static void
@@ -302,6 +307,48 @@ find_valid_session_keyfile (const char *session)
return keyfile;
}
+static GKeyFile *
+get_session_keyfile (const char *session)
+{
+ GKeyFile *keyfile;
+ gboolean session_runnable;
+ char *value;
+
+ g_debug ("fill: *** Getting session '%s'", session);
+
+ keyfile = find_valid_session_keyfile (session);
+
+ session_runnable = TRUE;
+
+ value = g_key_file_get_string (keyfile,
+ GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_RUNNABLE_KEY,
+ NULL);
+ if (!IS_STRING_EMPTY (value)) {
+ g_debug ("fill: *** Launching helper '%s' to know if session is runnable", value);
+ session_runnable = (gsm_process_helper (value, GSM_RUNNABLE_HELPER_TIMEOUT) == 0);
+ }
+ g_free (value);
+
+ if (session_runnable)
+ return keyfile;
+
+ g_debug ("fill: *** Session is not runnable");
+
+ /* We can't run this session, so try to use the fallback */
+ value = g_key_file_get_string (keyfile,
+ GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_FALLBACK_KEY,
+ NULL);
+
+ g_key_file_free (keyfile);
+ keyfile = NULL;
+
+ if (!IS_STRING_EMPTY (value))
+ keyfile = get_session_keyfile (value);
+ g_free (value);
+
+ return keyfile;
+}
+
gboolean
gsm_session_fill (GsmManager *manager,
char **override_autostart_dirs,
@@ -317,7 +364,7 @@ gsm_session_fill (GsmManager *manager,
if (IS_STRING_EMPTY (session))
session = GSM_DEFAULT_SESSION;
- keyfile = find_valid_session_keyfile (session);
+ keyfile = get_session_keyfile (session);
if (!keyfile)
return FALSE;
diff --git a/gnome-session/test-process-helper.c b/gnome-session/test-process-helper.c
new file mode 100644
index 0000000..50f79ad
--- /dev/null
+++ b/gnome-session/test-process-helper.c
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include "gsm-process-helper.h"
+
+int
+main (int argc,
+ char *argv[])
+{
+ int ret;
+ char *command_line = "xeyes";
+ int timeout = 500;
+
+ if (argc > 3) {
+ g_printerr ("Too many arguments.\n");
+ g_printerr ("Usage: %s [COMMAND] [TIMEOUT]\n", argv[0]);
+ return 1;
+ }
+
+ if (argc >= 2)
+ command_line = argv[1];
+ if (argc >= 3) {
+ int i = atoi (argv[2]);
+ if (i > 0)
+ timeout = i;
+ }
+
+ ret = gsm_process_helper (command_line, timeout);
+
+ if (ret < 0)
+ g_print ("Command did not succeed (or takes too much time).\n");
+ else
+ g_print ("Command returned %d.\n", ret);
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]