Add boot-manager Kill() method
authorJonathan Maw <jonathan.maw@codethink.co.uk>
Mon, 18 Jun 2012 10:01:48 +0000 (11:01 +0100)
committerJannis Pohlmann <jannis.pohlmann@codethink.co.uk>
Tue, 19 Jun 2012 13:27:19 +0000 (14:27 +0100)
The Kill() method differs from Start() and Stop() in the following ways:
- Systemd does not create jobs for KillUnit() operations, so it doesn't
  send a "job-removed" signal.
- The systemd method KillUnit() has different arguments. As well as the
  name and the mode, it also takes 'who' and 'signal' number.
  The 'who', 'mode' and 'signal' arguments currently use the default
  parameters of "all", "control-group" and SIGKILL, respectively.

boot-manager/boot-manager-application.c
boot-manager/boot-manager-service.c
boot-manager/boot-manager-service.h

index e49ad4c..50fc3c2 100644 (file)
@@ -164,6 +164,7 @@ boot_manager_application_set_property (GObject      *object,
 static void
 boot_manager_application_startup (GApplication *app)
 {
+  (*G_APPLICATION_CLASS (boot_manager_application_parent_class)->startup) (app);
 }
 
 
index 250e7bd..11454b7 100644 (file)
@@ -67,6 +67,18 @@ static void                   boot_manager_service_handle_stop_finish  (BootMana
 static void                   boot_manager_service_stop_unit_reply     (GObject                   *object,
                                                                         GAsyncResult              *result,
                                                                         gpointer                   user_data);
+static gboolean               boot_manager_service_handle_kill         (BootManager               *interface,
+                                                                        GDBusMethodInvocation     *invocation,
+                                                                        const gchar               *unit,
+                                                                        BootManagerService        *service);
+static void                   boot_manager_service_handle_kill_finish  (BootManagerService        *service,
+                                                                        const gchar               *unit,
+                                                                        const gchar               *result,
+                                                                        GError                    *error,
+                                                                        gpointer                   user_data);
+static void                   boot_manager_service_kill_unit_reply     (GObject                   *object,
+                                                                        GAsyncResult              *result,
+                                                                        gpointer                   user_data);
 static void                   boot_manager_service_job_removed         (SystemdManager            *manager,
                                                                         guint                      id,
                                                                         const gchar               *job_name,
@@ -169,6 +181,10 @@ boot_manager_service_init (BootManagerService *service)
   /* implement the Stop() method handler */
   g_signal_connect (service->interface, "handle-stop",
                     G_CALLBACK (boot_manager_service_handle_stop), service);
+
+  /* implement the Kill() method handler */
+  g_signal_connect (service->interface, "handle-kill",
+                    G_CALLBACK (boot_manager_service_handle_kill), service);
 }
 
 
@@ -322,7 +338,7 @@ boot_manager_service_start_unit_reply (GObject      *object,
   if (!systemd_manager_call_start_unit_finish (job->service->systemd_manager,
                                                &job_name, result, &error))
     {
-      /* there was an error; let the caller now */
+      /* there was an error; let the caller know */
       job->callback (job->service, job->unit, "failed", error, job->user_data);
       g_error_free (error);
       g_free (job_name);
@@ -420,6 +436,77 @@ boot_manager_service_stop_unit_reply (GObject      *object,
 
 
 
+static gboolean
+boot_manager_service_handle_kill (BootManager           *interface,
+                                  GDBusMethodInvocation *invocation,
+                                  const gchar           *unit,
+                                  BootManagerService    *service)
+{
+  g_return_val_if_fail (IS_BOOT_MANAGER (interface), FALSE);
+  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
+  g_return_val_if_fail (unit != NULL, FALSE);
+  g_return_val_if_fail (BOOT_MANAGER_IS_SERVICE (service), FALSE);  
+
+  /* ask systemd to kill the unit, send a D-Bus reply in the finish callback */
+  boot_manager_service_kill (service, unit, NULL, boot_manager_service_handle_kill_finish,
+                             invocation);
+
+  return TRUE;
+}
+
+
+
+static void
+boot_manager_service_handle_kill_finish (BootManagerService *service,
+                                         const gchar        *unit,
+                                         const gchar        *result,
+                                         GError             *error,
+                                         gpointer            user_data)
+{
+  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
+
+  g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
+  g_return_if_fail (unit!= NULL);
+  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
+
+  /* log any potential errors */
+  if (error != NULL)
+    g_warning ("there was an error: %s", error->message);
+
+  /* report the result back to the boot manager client */
+  boot_manager_complete_kill (service->interface, invocation, result);
+}
+
+
+
+static void
+boot_manager_service_kill_unit_reply (GObject      *object,
+                                      GAsyncResult *result,
+                                      gpointer      user_data)
+{
+  BootManagerServiceJob *job = user_data;
+  GError                *error = NULL;
+
+  g_return_if_fail (IS_SYSTEMD_MANAGER (object));
+  g_return_if_fail (G_IS_ASYNC_RESULT (result));
+  g_return_if_fail (user_data != NULL);
+
+  /* finish the kill unit call */
+  systemd_manager_call_kill_unit_finish (job->service->systemd_manager,
+                                         result, &error);
+
+  /* got a reply from systemd; let the caller know we're done */
+  job->callback (job->service, job->unit, (error == NULL) ? "done" : "failed", error,
+                 job->user_data);
+  if (error != NULL)
+    g_error_free (error);
+
+  /* finish the job */
+  boot_manager_service_job_unref (job);
+}
+
+
+
 static void
 boot_manager_service_job_removed (SystemdManager     *manager,
                                   guint               id,
@@ -607,3 +694,28 @@ boot_manager_service_stop (BootManagerService        *service,
   systemd_manager_call_stop_unit (service->systemd_manager, unit, "fail", cancellable,
                                   boot_manager_service_stop_unit_reply, job);
 }
+
+
+
+void
+boot_manager_service_kill (BootManagerService        *service,
+                           const gchar               *unit,
+                           GCancellable              *cancellable,
+                           BootManagerServiceCallback callback,
+                           gpointer                   user_data)
+{
+  BootManagerServiceJob *job;
+
+  g_return_if_fail (BOOT_MANAGER_IS_SERVICE (service));
+  g_return_if_fail (unit != NULL);
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+  g_return_if_fail (callback != NULL);
+
+  /* create a new job object */
+  job = boot_manager_service_job_new (service, unit, cancellable, callback, user_data);
+
+  /* ask systemd to stop the unit asynchronously */
+  systemd_manager_call_kill_unit (service->systemd_manager, unit, "all", "control-group",
+                                  SIGKILL, cancellable,
+                                  boot_manager_service_kill_unit_reply, job);
+}
index 3c7affd..d174d37 100644 (file)
@@ -46,6 +46,11 @@ void                boot_manager_service_stop     (BootManagerService        *se
                                                    GCancellable              *cancellable,
                                                    BootManagerServiceCallback callback,
                                                    gpointer                   user_data);
+void                boot_manager_service_kill     (BootManagerService        *service,
+                                                   const gchar               *unit,
+                                                   GCancellable              *cancellable,
+                                                   BootManagerServiceCallback callback,
+                                                   gpointer                   user_data);
 
 G_END_DECLS