[gnome-session] Handle required component failure by showing fail whale
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-session] Handle required component failure by showing fail whale
- Date: Thu, 17 Mar 2011 16:14:58 +0000 (UTC)
commit 9a4ff4b674fb7b63fd361eeedd4925ad84c67686
Author: Colin Walters <walters verbum org>
Date: Thu Mar 10 18:56:39 2011 -0500
Handle required component failure by showing fail whale
When a required component either times out on startup, or
is killed by a fatal signal, toss up a fail whale dialog.
https://bugzilla.gnome.org/show_bug.cgi?id=642497
gnome-session/gsm-manager.c | 112 +++++++++++++++++++++++++++++++++++---
gnome-session/gsm-manager.h | 3 +
gnome-session/gsm-session-fill.c | 2 +-
3 files changed, 107 insertions(+), 10 deletions(-)
---
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
index f7616ec..8b35f14 100644
--- a/gnome-session/gsm-manager.c
+++ b/gnome-session/gsm-manager.c
@@ -59,6 +59,7 @@
#include "gsm-util.h"
#include "gdm.h"
#include "gsm-logout-dialog.h"
+#include "gsm-fail-whale-dialog.h"
#include "gsm-inhibit-dialog.h"
#include "gsm-consolekit.h"
#include "gsm-session-save.h"
@@ -85,6 +86,8 @@
#define SCREENSAVER_SCHEMA "org.gnome.desktop.screensaver"
#define KEY_SLEEP_LOCK "lock-enabled"
+static void app_registered (GsmApp *app, GsmManager *manager);
+
typedef enum
{
GSM_MANAGER_LOGOUT_NONE,
@@ -111,6 +114,7 @@ struct GsmManagerPrivate
/* Current status */
GsmManagerPhase phase;
guint phase_timeout_id;
+ GSList *required_apps;
GSList *pending_apps;
GsmManagerLogoutMode logout_mode;
GSList *query_clients;
@@ -222,6 +226,28 @@ gsm_manager_error_get_type (void)
}
static gboolean
+is_app_required (GsmManager *manager,
+ GsmApp *app)
+{
+ return g_slist_find (manager->priv->required_apps, app) != NULL;
+}
+
+static void
+on_required_app_failure (GsmManager *manager,
+ GsmApp *app,
+ const char *msg)
+{
+ char *full_msg;
+ full_msg = g_strdup_printf ("Component '%s': %s",
+ gsm_app_peek_app_id (app),
+ msg);
+ gsm_fail_whale_dialog_we_failed (GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_FATAL,
+ full_msg);
+ g_free (full_msg);
+}
+
+
+static gboolean
_debug_client (const char *id,
GsmClient *client,
GsmManager *manager)
@@ -516,9 +542,28 @@ end_phase (GsmManager *manager)
}
static void
+app_died (GsmApp *app,
+ GsmManager *manager)
+{
+ manager->priv->pending_apps = g_slist_remove (manager->priv->pending_apps, app);
+ g_signal_handlers_disconnect_by_func (app, app_registered, manager);
+
+ g_warning ("Application '%s' killed by signal", gsm_app_peek_app_id (app));
+ if (is_app_required (manager, app))
+ on_required_app_failure (manager, app, "Killed by signal");
+ /* For now, we don't do anything with crashes from non-required apps;
+ * practically speaking they will be caught by ABRT/apport type
+ * infrastructure, and it'd be better to pick up the crash from
+ * there and do something un-intrusive about it generically.
+ */
+}
+
+static void
app_registered (GsmApp *app,
GsmManager *manager)
{
+ g_debug ("App %s registered", gsm_app_peek_app_id (app));
+
manager->priv->pending_apps = g_slist_remove (manager->priv->pending_apps, app);
g_signal_handlers_disconnect_by_func (app, app_registered, manager);
@@ -556,10 +601,12 @@ on_phase_timeout (GsmManager *manager)
case GSM_MANAGER_PHASE_DESKTOP:
case GSM_MANAGER_PHASE_APPLICATION:
for (a = manager->priv->pending_apps; a; a = a->next) {
+ GsmApp *app = a->data;
g_warning ("Application '%s' failed to register before timeout",
- gsm_app_peek_app_id (a->data));
- g_signal_handlers_disconnect_by_func (a->data, app_registered, manager);
- /* FIXME: what if the app was filling in a required slot? */
+ gsm_app_peek_app_id (app));
+ g_signal_handlers_disconnect_by_func (app, app_registered, manager);
+ if (is_app_required (manager, app))
+ on_required_app_failure (manager, app, _("Timed out"));
}
break;
case GSM_MANAGER_PHASE_RUNNING:
@@ -638,6 +685,10 @@ _start_app (const char *id,
"registered",
G_CALLBACK (app_registered),
manager);
+ g_signal_connect (app,
+ "died",
+ G_CALLBACK (app_died),
+ manager);
manager->priv->pending_apps = g_slist_prepend (manager->priv->pending_apps, app);
}
out:
@@ -2382,6 +2433,9 @@ gsm_manager_dispose (GObject *object)
manager->priv->apps = NULL;
}
+ g_slist_free (manager->priv->required_apps);
+ manager->priv->required_apps = NULL;
+
if (manager->priv->inhibitors != NULL) {
g_signal_handlers_disconnect_by_func (manager->priv->inhibitors,
on_store_inhibitor_added,
@@ -3684,7 +3738,8 @@ gsm_manager_is_autostart_condition_handled (GsmManager *manager,
static void
append_app (GsmManager *manager,
- GsmApp *app)
+ GsmApp *app,
+ gboolean is_required)
{
const char *id;
const char *app_id;
@@ -3715,12 +3770,17 @@ append_app (GsmManager *manager,
}
gsm_store_add (manager->priv->apps, id, G_OBJECT (app));
+ if (is_required) {
+ g_debug ("GsmManager: adding required app %s", gsm_app_peek_app_id (app));
+ manager->priv->required_apps = g_slist_prepend (manager->priv->required_apps, app);
+ }
}
-gboolean
-gsm_manager_add_autostart_app (GsmManager *manager,
- const char *path,
- const char *provides)
+static gboolean
+add_autostart_app_internal (GsmManager *manager,
+ const char *path,
+ const char *provides,
+ gboolean is_required)
{
GsmApp *app;
@@ -3747,13 +3807,47 @@ gsm_manager_add_autostart_app (GsmManager *manager,
}
g_debug ("GsmManager: read %s", path);
- append_app (manager, app);
+ append_app (manager, app, is_required);
g_object_unref (app);
return TRUE;
}
gboolean
+gsm_manager_add_autostart_app (GsmManager *manager,
+ const char *path,
+ const char *provides)
+{
+ return add_autostart_app_internal (manager,
+ path,
+ provides,
+ FALSE);
+}
+
+/**
+ * gsm_manager_add_required_app:
+ * @manager: a #GsmManager
+ * @path: Path to desktop file
+ * @provides: What the component provides, as a space separated list
+ *
+ * Similar to gsm_manager_add_autostart_app(), except marks the
+ * component as being required; we then try harder to ensure
+ * it's running and inform the user if we can't.
+ *
+ */
+gboolean
+gsm_manager_add_required_app (GsmManager *manager,
+ const char *path,
+ const char *provides)
+{
+ return add_autostart_app_internal (manager,
+ path,
+ provides,
+ TRUE);
+}
+
+
+gboolean
gsm_manager_add_autostart_apps_from_dir (GsmManager *manager,
const char *path)
{
diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h
index d75bba0..c878280 100644
--- a/gnome-session/gsm-manager.h
+++ b/gnome-session/gsm-manager.h
@@ -120,6 +120,9 @@ gboolean gsm_manager_get_failsafe (GsmManager *
gboolean gsm_manager_add_autostart_app (GsmManager *manager,
const char *path,
const char *provides);
+gboolean gsm_manager_add_required_app (GsmManager *manager,
+ const char *path,
+ const char *provides);
gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager,
const char *path);
gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager,
diff --git a/gnome-session/gsm-session-fill.c b/gnome-session/gsm-session-fill.c
index 8e787e9..07b5b3d 100644
--- a/gnome-session/gsm-session-fill.c
+++ b/gnome-session/gsm-session-fill.c
@@ -112,7 +112,7 @@ append_required_apps (GsmManager *manager,
g_debug ("fill: %s looking for component: '%s'", required_components[i], value);
app_path = gsm_util_find_desktop_file_for_app_name (value, NULL);
if (app_path != NULL) {
- gsm_manager_add_autostart_app (manager, app_path, required_components[i]);
+ gsm_manager_add_required_app (manager, app_path, required_components[i]);
} else {
g_warning ("Unable to find provider '%s' of required component '%s'",
value, required_components[i]);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]