Commit c33467d2 authored by Simon McVittie's avatar Simon McVittie

CbyServiceManager: Implement a method to stop an entire app-bundle

This is essentially the same as stopping individual entry points
(it's just a StopUnit() call) so repurpose the infrastructure we use
for that.
Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
Reviewed-by: Frédéric Dalleau's avatarFrédéric Dalleau <frederic.dalleau@collabora.co.uk>
Differential Revision: https://phabricator.apertis.org/D7071
parent 84f3d0c3
......@@ -1722,6 +1722,7 @@ job_removed_cb (GDBusConnection *connection,
g_autofree gchar *job_path = NULL;
g_autofree gchar *service_name = NULL;
g_autofree gchar *job_result = NULL;
gconstpointer tag;
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uoss)")))
{
......@@ -1742,23 +1743,26 @@ job_removed_cb (GDBusConnection *connection,
return;
}
tag = g_task_get_source_tag (task);
if (g_strcmp0 (job_result, "done") == 0)
{
if (g_task_get_source_tag (task) == _cby_service_manager_start_service_async)
if (tag == _cby_service_manager_start_service_async)
{
/* Job started, do another round to get the service PID */
get_service_dbus_path_and_pid (self, service_name, task);
}
else
{
g_assert (g_task_get_source_tag (task) ==
_cby_service_manager_stop_service_async);
g_assert (tag == _cby_service_manager_stop_service_async ||
tag == _cby_service_manager_stop_bundle_async);
g_task_return_boolean (task, TRUE);
}
}
else
{
if (g_task_get_source_tag (task) == _cby_service_manager_start_service_async)
if (tag == _cby_service_manager_start_service_async)
{
g_autoptr (GError) error = NULL;
ServiceInfo *service_info = g_task_get_task_data (task);
......@@ -1772,10 +1776,10 @@ job_removed_cb (GDBusConnection *connection,
{
g_autoptr (GError) error = NULL;
g_assert (g_task_get_source_tag (task) ==
_cby_service_manager_stop_service_async);
g_assert (tag == _cby_service_manager_stop_service_async ||
tag == _cby_service_manager_stop_bundle_async);
g_set_error (&error, CBY_ERROR, CBY_ERROR_FAILED,
"Failed to stop service \"%s\": %s",
"Failed to stop unit \"%s\": %s",
service_name, job_result);
g_task_return_error (task, g_steal_pointer (&error));
}
......@@ -1962,10 +1966,13 @@ start_service (CbyServiceManager *self,
g_steal_pointer (&task));
}
/*
* Async callback for any StopUnit() call with a GTask as user_data
*/
static void
stop_service_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
stop_unit_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
g_autoptr (GTask) task = user_data;
g_autoptr (GError) error = NULL;
......@@ -2025,7 +2032,7 @@ stop_service_async (CbyServiceManager *self,
G_DBUS_CALL_FLAGS_NONE,
-1,
g_task_get_cancellable (task),
stop_service_cb,
stop_unit_cb,
g_object_ref (task));
}
......@@ -2146,6 +2153,56 @@ _cby_service_manager_stop_service_finish (CbyServiceManager *self,
return g_task_propagate_boolean (G_TASK (result), error);
}
void
_cby_service_manager_stop_bundle_async (CbyServiceManager *self,
const gchar *bundle_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr (GTask) task = NULL;
g_autofree gchar *unit_name = NULL;
g_return_if_fail (CBY_IS_SERVICE_MANAGER (self));
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, _cby_service_manager_stop_bundle_async);
/* All services for bundle com.example.Foo are placed in
* com.example.Foo.slice. We don't need to worry about whether the slice
* is empty, or even whether it exists at all, because StopUnit() on a
* nonexistent slice just returns a job that is immediately removed
* as "done". */
unit_name = g_strdup_printf ("%s.slice", bundle_id);
ensure_change_notification_subscription (self);
g_dbus_connection_call (self->session_bus,
SYSTEMD_BUS_NAME,
SYSTEMD_PATH_MANAGER,
SYSTEMD_IFACE_MANAGER,
"StopUnit",
g_variant_new ("(ss)", unit_name, "replace"),
G_VARIANT_TYPE ("(o)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
g_task_get_cancellable (task),
stop_unit_cb,
g_object_ref (task));
}
gboolean
_cby_service_manager_stop_bundle_finish (CbyServiceManager *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (CBY_IS_SERVICE_MANAGER (self), FALSE);
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
g_return_val_if_fail (g_async_result_is_tagged (result,
_cby_service_manager_stop_bundle_async),
FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
void
_cby_service_manager_signal_service_async (CbyServiceManager *self,
CbyEntryPoint *entry_point,
......
......@@ -74,6 +74,15 @@ gboolean _cby_service_manager_start_agents_finish (CbyServiceManager *self,
GAsyncResult *result,
GError **error);
void _cby_service_manager_stop_bundle_async (CbyServiceManager *self,
const gchar *bundle_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean _cby_service_manager_stop_bundle_finish (CbyServiceManager *self,
GAsyncResult *result,
GError **error);
G_END_DECLS
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment