Cancel all LUC app start operations when receiving SIGINT
authorJonathan Maw <jonathan.maw@codethink.co.uk>
Wed, 20 Jun 2012 16:08:03 +0000 (17:08 +0100)
committerJonathan Maw <jonathan.maw@codethink.co.uk>
Thu, 21 Jun 2012 11:05:43 +0000 (12:05 +0100)
We add a signal handler for SIGINT which calls the luc_starter_cancel()
method. luc_starter_cancel(), in turn, cancels every D-Bus call to
create a start unit job.
Unfortunately, once a start unit job has been created, cancelling will
not cancel the job to start a unit.

boot-manager/boot-manager-application.c
boot-manager/luc-starter.c
boot-manager/luc-starter.h

index f64d6f1..349b228 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <glib-object.h>
 #include <gio/gio.h>
+#include <glib-unix.h>
 
 #include <common/watchdog-client.h>
 
@@ -35,17 +36,18 @@ enum
 
 
 
-static void boot_manager_application_finalize     (GObject      *object);
-static void boot_manager_application_constructed  (GObject      *object);
-static void boot_manager_application_get_property (GObject      *object,
-                                                   guint         prop_id,
-                                                   GValue       *value,
-                                                   GParamSpec   *pspec);
-static void boot_manager_application_set_property (GObject      *object,
-                                                   guint         prop_id,
-                                                   const GValue *value,
-                                                   GParamSpec   *pspec);
-static void boot_manager_application_startup      (GApplication *application);
+static void     boot_manager_application_finalize     (GObject      *object);
+static void     boot_manager_application_constructed  (GObject      *object);
+static void     boot_manager_application_get_property (GObject      *object,
+                                                       guint         prop_id,
+                                                       GValue       *value,
+                                                       GParamSpec   *pspec);
+static void     boot_manager_application_set_property (GObject      *object,
+                                                       guint         prop_id,
+                                                       const GValue *value,
+                                                       GParamSpec   *pspec);
+static void     boot_manager_application_startup      (GApplication *application);
+static gboolean boot_manager_application_int_handler  (GApplication *application);
 
 
 
@@ -68,6 +70,9 @@ struct _BootManagerApplication
   /* LUC starter to restore the LUC */
   LUCHandler         *luc_handler;
   LUCStarter         *luc_starter;
+
+  /* signal handler IDs */
+  guint               sigint_id;
 };
 
 
@@ -129,6 +134,11 @@ boot_manager_application_init (BootManagerApplication *application)
 {
   /* update systemd's watchdog timestamp every 120 seconds */
   application->watchdog_client = watchdog_client_new (120);
+
+  /* install the signal handler */
+  application->sigint_id =
+    g_unix_signal_add (SIGINT, (GSourceFunc) boot_manager_application_int_handler,
+                       application);
 }
 
 
@@ -138,6 +148,9 @@ boot_manager_application_finalize (GObject *object)
 {
   BootManagerApplication *application = BOOT_MANAGER_APPLICATION (object);
 
+  /* release the signal handler */
+  g_source_remove (application->sigint_id);
+
   /* release the watchdog client */
   g_object_unref (application->watchdog_client);
 
@@ -231,6 +244,18 @@ boot_manager_application_startup (GApplication *app)
 
 
 
+static gboolean
+boot_manager_application_int_handler (GApplication *app)
+{
+  BootManagerApplication *application = BOOT_MANAGER_APPLICATION (app);
+
+  luc_starter_cancel (application->luc_starter);
+
+  return TRUE;
+}
+
+
+
 BootManagerApplication *
 boot_manager_application_new (BootManagerService *boot_manager,
                               LUCHandler         *luc_handler)
index 891e988..338af01 100644 (file)
@@ -51,6 +51,9 @@ static void luc_starter_start_app_finish  (BootManagerService *service,
                                            const gchar        *result,
                                            GError             *error,
                                            gpointer            user_data);
+static void luc_starter_cancel_start      (const gchar        *app,
+                                           GCancellable       *cancellable,
+                                           gpointer            user_data);
 
 
 
@@ -313,6 +316,10 @@ luc_starter_start_app_finish (BootManagerService *service,
 
   g_debug ("start app '%s' finish", unit);
 
+  /* respond to errors */
+  if (error != NULL)
+    g_warning ("start app had error: %s", error->message);
+
   /* get the current start group */
   group_name = starter->start_order->data;
 
@@ -357,6 +364,16 @@ luc_starter_start_app_finish (BootManagerService *service,
 
 
 
+static void
+luc_starter_cancel_start (const gchar  *app,
+                          GCancellable *cancellable,
+                          gpointer      user_data)
+{
+  g_cancellable_cancel (cancellable);
+}
+
+
+
 LUCStarter *
 luc_starter_new (BootManagerService *boot_manager,
                  LUCHandler         *luc_handler)
@@ -452,3 +469,9 @@ luc_starter_start_groups (LUCStarter *starter)
   if (starter->start_order != NULL)
     luc_starter_start_next_group (starter);
 }
+
+void
+luc_starter_cancel (LUCStarter *starter)
+{
+  g_hash_table_foreach (starter->cancellables, (GHFunc) luc_starter_cancel_start, NULL);
+}
index 7645dbe..2f6db6e 100644 (file)
@@ -30,6 +30,7 @@ GType       luc_starter_get_type     (void) G_GNUC_CONST;
 LUCStarter *luc_starter_new          (BootManagerService *boot_manager,
                                       LUCHandler         *luc_handler) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 void        luc_starter_start_groups (LUCStarter         *starter);
+void        luc_starter_cancel       (LUCStarter         *starter);
 
 G_END_DECLS