File gnome-settings-daemon-grd-assigned-handover-service.patch of Package gnome-settings-daemon
From 23decd3f845390527b71bc548765b6cce0d42001 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 1 Nov 2023 10:04:20 -0400
Subject: [PATCH 1/5] sharing: Make systemd helpers take service name instead
of ServiceInfo
A future commit is going to introduce a different type of service, and
that commit will need to be able to start and stop services too.
This commit prepares for that by making the APIs for managing services
take service names instead of ServiceInfo instances.
---
plugins/sharing/gsd-sharing-manager.c | 29 ++++++++++++++++-----------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/plugins/sharing/gsd-sharing-manager.c b/plugins/sharing/gsd-sharing-manager.c
index aca78b396..7c6d06e25 100644
--- a/plugins/sharing/gsd-sharing-manager.c
+++ b/plugins/sharing/gsd-sharing-manager.c
@@ -92,6 +92,11 @@ static void gsd_sharing_manager_class_init (GsdSharingManagerClass *klass);
static void gsd_sharing_manager_init (GsdSharingManager *manager);
static void gsd_sharing_manager_finalize (GObject *object);
+static void gsd_sharing_manager_start_service (GsdSharingManager *manager,
+ const char *service_name);
+static void gsd_sharing_manager_stop_service (GsdSharingManager *manager,
+ const char *service_name);
+
G_DEFINE_TYPE (GsdSharingManager, gsd_sharing_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
@@ -129,11 +134,11 @@ handle_unit_cb (GObject *source_object,
static void
gsd_sharing_manager_handle_service (GsdSharingManager *manager,
const char *method,
- ServiceInfo *service)
+ const char *service_name)
{
char *service_file;
- service_file = g_strdup_printf ("%s.service", service->name);
+ service_file = g_strdup_printf ("%s.service", service_name);
g_dbus_connection_call (manager->connection,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -151,23 +156,23 @@ gsd_sharing_manager_handle_service (GsdSharingManager *manager,
static void
gsd_sharing_manager_start_service (GsdSharingManager *manager,
- ServiceInfo *service)
+ const char *service_name)
{
- g_debug ("About to start %s", service->name);
+ g_debug ("About to start %s", service_name);
/* We use StartUnit, not StartUnitReplace, since the latter would
* cancel any pending start we already have going from an
* earlier _start_service() call */
- gsd_sharing_manager_handle_service (manager, "StartUnit", service);
+ gsd_sharing_manager_handle_service (manager, "StartUnit", service_name);
}
static void
gsd_sharing_manager_stop_service (GsdSharingManager *manager,
- ServiceInfo *service)
+ const char *service_name)
{
- g_debug ("About to stop %s", service->name);
+ g_debug ("About to stop %s", service_name);
- gsd_sharing_manager_handle_service (manager, "StopUnit", service);
+ gsd_sharing_manager_handle_service (manager, "StopUnit", service_name);
}
#if HAVE_NETWORK_MANAGER
@@ -215,9 +220,9 @@ gsd_sharing_manager_sync_services (GsdSharingManager *manager)
should_be_started = TRUE;
if (should_be_started)
- gsd_sharing_manager_start_service (manager, service);
+ gsd_sharing_manager_start_service (manager, service->name);
else
- gsd_sharing_manager_stop_service (manager, service);
+ gsd_sharing_manager_stop_service (manager, service->name);
}
g_list_free (services);
}
@@ -322,7 +327,7 @@ gsd_sharing_manager_enable_service (GsdSharingManager *manager,
bail:
- gsd_sharing_manager_start_service (manager, service);
+ gsd_sharing_manager_start_service (manager, service->name);
g_ptr_array_unref (array);
g_strfreev (connections);
@@ -358,7 +363,7 @@ gsd_sharing_manager_disable_service (GsdSharingManager *manager,
g_strfreev (connections);
if (g_str_equal (network_name, manager->current_network))
- gsd_sharing_manager_stop_service (manager, service);
+ gsd_sharing_manager_stop_service (manager, service->name);
return TRUE;
}
--
GitLab
From 483a23a80e95541c008e2e32b62895e97c8561e6 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 1 Nov 2023 10:08:47 -0400
Subject: [PATCH 2/5] sharing: Move initial service management to own function
This is just refactoring clean up in prep for future changes.
---
plugins/sharing/gsd-sharing-manager.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/plugins/sharing/gsd-sharing-manager.c b/plugins/sharing/gsd-sharing-manager.c
index 7c6d06e25..17d1fc60c 100644
--- a/plugins/sharing/gsd-sharing-manager.c
+++ b/plugins/sharing/gsd-sharing-manager.c
@@ -773,17 +773,9 @@ service_free (gpointer pointer)
}
static void
-gsd_sharing_manager_init (GsdSharingManager *manager)
+manage_services (GsdSharingManager *manager)
{
- guint i;
-
- manager->services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, service_free);
-
- /* Default state */
- manager->current_network = g_strdup ("");
- manager->current_network_name = g_strdup ("");
- manager->carrier_type = g_strdup ("");
- manager->sharing_status = GSD_SHARING_STATUS_OFFLINE;
+ size_t i;
for (i = 0; i < G_N_ELEMENTS (services); i++) {
ServiceInfo *service;
@@ -799,6 +791,20 @@ gsd_sharing_manager_init (GsdSharingManager *manager)
}
}
+static void
+gsd_sharing_manager_init (GsdSharingManager *manager)
+{
+ manager->services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, service_free);
+
+ /* Default state */
+ manager->current_network = g_strdup ("");
+ manager->current_network_name = g_strdup ("");
+ manager->carrier_type = g_strdup ("");
+ manager->sharing_status = GSD_SHARING_STATUS_OFFLINE;
+
+ manage_services (manager);
+}
+
static void
gsd_sharing_manager_finalize (GObject *object)
{
--
GitLab
From 663598710cd2cb09e5117025ef1798c4a4820d17 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 3 Nov 2023 10:40:23 -0400
Subject: [PATCH 3/5] sharing: Rename `services` to `configurable_services`
We're going to have "assigned" services soon that are delegated from
systemd system services. In order to avoid ambiguity, this commit
prepares for that, by renaming the existing `services` variable to
`configurable_services`
---
plugins/sharing/gsd-sharing-manager.c | 56 +++++++++++++--------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/plugins/sharing/gsd-sharing-manager.c b/plugins/sharing/gsd-sharing-manager.c
index 17d1fc60c..cbfdad06b 100644
--- a/plugins/sharing/gsd-sharing-manager.c
+++ b/plugins/sharing/gsd-sharing-manager.c
@@ -36,7 +36,7 @@
typedef struct {
const char *name;
GSettings *settings;
-} ServiceInfo;
+} ConfigurableServiceInfo;
struct _GsdSharingManager
{
@@ -51,7 +51,7 @@ struct _GsdSharingManager
NMClient *client;
#endif /* HAVE_NETWORK_MANAGER */
- GHashTable *services;
+ GHashTable *configurable_services;
char *current_network;
char *current_network_name;
@@ -101,7 +101,7 @@ G_DEFINE_TYPE (GsdSharingManager, gsd_sharing_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
-static const char * const services[] = {
+static const char * const configurable_services[] = {
"rygel",
"gnome-user-share-webdav"
};
@@ -177,8 +177,8 @@ gsd_sharing_manager_stop_service (GsdSharingManager *manager,
#if HAVE_NETWORK_MANAGER
static gboolean
-service_is_enabled_on_current_connection (GsdSharingManager *manager,
- ServiceInfo *service)
+service_is_enabled_on_current_connection (GsdSharingManager *manager,
+ ConfigurableServiceInfo *service)
{
char **connections;
int j;
@@ -197,8 +197,8 @@ service_is_enabled_on_current_connection (GsdSharingManager *manager,
}
#else
static gboolean
-service_is_enabled_on_current_connection (GsdSharingManager *manager,
- ServiceInfo *service)
+service_is_enabled_on_current_connection (GsdSharingManager *manager,
+ ConfigurableServiceInfo *service)
{
return FALSE;
}
@@ -209,10 +209,10 @@ gsd_sharing_manager_sync_services (GsdSharingManager *manager)
{
GList *services, *l;
- services = g_hash_table_get_values (manager->services);
+ services = g_hash_table_get_values (manager->configurable_services);
for (l = services; l != NULL; l = l->next) {
- ServiceInfo *service = l->data;
+ ConfigurableServiceInfo *service = l->data;
gboolean should_be_started = FALSE;
if (manager->sharing_status == GSD_SHARING_STATUS_AVAILABLE &&
@@ -265,9 +265,9 @@ static char **
get_connections_for_service (GsdSharingManager *manager,
const char *service_name)
{
- ServiceInfo *service;
+ ConfigurableServiceInfo *service;
- service = g_hash_table_lookup (manager->services, service_name);
+ service = g_hash_table_lookup (manager->configurable_services, service_name);
return g_settings_get_strv (service->settings, "enabled-connections");
}
#else
@@ -285,7 +285,7 @@ check_service (GsdSharingManager *manager,
const char *service_name,
GError **error)
{
- if (g_hash_table_lookup (manager->services, service_name))
+ if (g_hash_table_lookup (manager->configurable_services, service_name))
return TRUE;
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
@@ -298,7 +298,7 @@ gsd_sharing_manager_enable_service (GsdSharingManager *manager,
const char *service_name,
GError **error)
{
- ServiceInfo *service;
+ ConfigurableServiceInfo *service;
char **connections;
GPtrArray *array;
guint i;
@@ -312,7 +312,7 @@ gsd_sharing_manager_enable_service (GsdSharingManager *manager,
return FALSE;
}
- service = g_hash_table_lookup (manager->services, service_name);
+ service = g_hash_table_lookup (manager->configurable_services, service_name);
connections = g_settings_get_strv (service->settings, "enabled-connections");
array = g_ptr_array_new ();
for (i = 0; connections[i] != NULL; i++) {
@@ -341,7 +341,7 @@ gsd_sharing_manager_disable_service (GsdSharingManager *manager,
const char *network_name,
GError **error)
{
- ServiceInfo *service;
+ ConfigurableServiceInfo *service;
char **connections;
GPtrArray *array;
guint i;
@@ -349,7 +349,7 @@ gsd_sharing_manager_disable_service (GsdSharingManager *manager,
if (!check_service (manager, service_name, error))
return FALSE;
- service = g_hash_table_lookup (manager->services, service_name);
+ service = g_hash_table_lookup (manager->configurable_services, service_name);
connections = g_settings_get_strv (service->settings, "enabled-connections");
array = g_ptr_array_new ();
for (i = 0; connections[i] != NULL; i++) {
@@ -764,37 +764,37 @@ gsd_sharing_manager_class_init (GsdSharingManagerClass *klass)
}
static void
-service_free (gpointer pointer)
+configurable_service_free (gpointer pointer)
{
- ServiceInfo *service = pointer;
+ ConfigurableServiceInfo *service = pointer;
g_clear_object (&service->settings);
g_free (service);
}
static void
-manage_services (GsdSharingManager *manager)
+manage_configurable_services (GsdSharingManager *manager)
{
size_t i;
- for (i = 0; i < G_N_ELEMENTS (services); i++) {
- ServiceInfo *service;
+ for (i = 0; i < G_N_ELEMENTS (configurable_services); i++) {
+ ConfigurableServiceInfo *service;
char *path;
- service = g_new0 (ServiceInfo, 1);
- service->name = services[i];
- path = g_strdup_printf ("/org/gnome/settings-daemon/plugins/sharing/%s/", services[i]);
+ service = g_new0 (ConfigurableServiceInfo, 1);
+ service->name = configurable_services[i];
+ path = g_strdup_printf ("/org/gnome/settings-daemon/plugins/sharing/%s/", configurable_services[i]);
service->settings = g_settings_new_with_path ("org.gnome.settings-daemon.plugins.sharing.service", path);
g_free (path);
- g_hash_table_insert (manager->services, (gpointer) services[i], service);
+ g_hash_table_insert (manager->configurable_services, (gpointer) configurable_services[i], service);
}
}
static void
gsd_sharing_manager_init (GsdSharingManager *manager)
{
- manager->services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, service_free);
+ manager->configurable_services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, configurable_service_free);
/* Default state */
manager->current_network = g_strdup ("");
@@ -802,7 +802,7 @@ gsd_sharing_manager_init (GsdSharingManager *manager)
manager->carrier_type = g_strdup ("");
manager->sharing_status = GSD_SHARING_STATUS_OFFLINE;
- manage_services (manager);
+ manage_configurable_services (manager);
}
static void
@@ -819,7 +819,7 @@ gsd_sharing_manager_finalize (GObject *object)
gsd_sharing_manager_stop (manager);
- g_hash_table_unref (manager->services);
+ g_hash_table_unref (manager->configurable_services);
G_OBJECT_CLASS (gsd_sharing_manager_parent_class)->finalize (object);
}
--
GitLab
From 0bfc60813befb45e3dd4840795839806f5310e39 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 3 Nov 2023 10:40:32 -0400
Subject: [PATCH 4/5] sharing: Start grd --handover if grd --system is running
In order to provide a login screen over gnome-remote-desktop,
their needs to be both system and session instance of
gnome-remote-desktop. The latter should get run if the former
is running, and not otherwise.
This commit adds a mechanism for doing this by introducing the
concept of "assigned services" (versus the already existing
configurable services).
Assigned services don't start based on GSettings configuration,
but instead just start if an associated system service is running.
---
meson.build | 3 +
plugins/sharing/gsd-sharing-manager.c | 281 +++++++++++++++++++++++++-
plugins/sharing/meson.build | 3 +-
3 files changed, 285 insertions(+), 2 deletions(-)
diff --git a/meson.build b/meson.build
index 28d580447..73378be0d 100644
--- a/meson.build
+++ b/meson.build
@@ -115,6 +115,9 @@ if enable_systemd
systemd_dep = dependency('systemd', version: '>= 243', required: false)
assert(systemd_dep.found(), 'Systemd support explicitly required, but systemd not found')
+ libsystemd_dep = dependency('libsystemd', version: '>= 243', required: false)
+ assert(libsystemd_dep.found(), 'Systemd support explicitly required, but libsystemd not found')
+
systemd_userunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
define_variable: ['prefix', gsd_prefix])
endif
diff --git a/plugins/sharing/gsd-sharing-manager.c b/plugins/sharing/gsd-sharing-manager.c
index cbfdad06b..c9d890f5e 100644
--- a/plugins/sharing/gsd-sharing-manager.c
+++ b/plugins/sharing/gsd-sharing-manager.c
@@ -20,6 +20,7 @@
#include "config.h"
#include <locale.h>
+#include <systemd/sd-login.h>
#include <glib.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
@@ -38,6 +39,22 @@ typedef struct {
GSettings *settings;
} ConfigurableServiceInfo;
+typedef struct {
+ const char *system_bus_name;
+ const char *user_service_desktop_id;
+ const char *user_service_name;
+ const char *local_session_classes[3];
+ const char *remote_session_classes[3];
+} AssignedService;
+
+typedef struct {
+ AssignedService *service;
+ guint system_bus_name_watch;
+ gboolean system_service_running;
+ GPid pid;
+ guint child_watch_id;
+} AssignedServiceInfo;
+
struct _GsdSharingManager
{
GObject parent;
@@ -52,11 +69,14 @@ struct _GsdSharingManager
#endif /* HAVE_NETWORK_MANAGER */
GHashTable *configurable_services;
+ GHashTable *assigned_services;
char *current_network;
char *current_network_name;
char *carrier_type;
GsdSharingStatus sharing_status;
+
+ gboolean is_systemd_managed;
};
#define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
@@ -106,6 +126,18 @@ static const char * const configurable_services[] = {
"gnome-user-share-webdav"
};
+/* Services that are delegated to the user session by a system service
+ */
+static AssignedService assigned_services[] = {
+ {
+ .system_bus_name = "org.gnome.RemoteDesktop",
+ .user_service_desktop_id = "org.gnome.RemoteDesktop.Handover.desktop",
+ .user_service_name = "gnome-remote-desktop-handover",
+ .local_session_classes = { NULL },
+ .remote_session_classes = { "user", "greeter", NULL }
+ }
+};
+
static void
handle_unit_cb (GObject *source_object,
GAsyncResult *res,
@@ -205,7 +237,7 @@ service_is_enabled_on_current_connection (GsdSharingManager *manager,
#endif /* HAVE_NETWORK_MANAGER */
static void
-gsd_sharing_manager_sync_services (GsdSharingManager *manager)
+gsd_sharing_manager_sync_configurable_services (GsdSharingManager *manager)
{
GList *services, *l;
@@ -227,6 +259,123 @@ gsd_sharing_manager_sync_services (GsdSharingManager *manager)
g_list_free (services);
}
+
+static void
+on_assigned_service_finished (GPid pid,
+ int exit_status,
+ gpointer user_data)
+{
+ AssignedServiceInfo *info = user_data;
+ AssignedService *service = info->service;
+
+ g_debug ("%s with pid %d exited with status %d", service->user_service_name, (int) pid, exit_status);
+
+ info->pid = 0;
+ info->child_watch_id = 0;
+}
+
+static void
+on_assigned_service_started (GDesktopAppInfo *app_info,
+ GPid pid,
+ gpointer user_data)
+{
+ AssignedServiceInfo *info = user_data;
+ AssignedService *service = info->service;
+
+ g_debug ("%s started with pid %d", service->user_service_name, (int) pid);
+
+ info->pid = pid;
+ info->child_watch_id = g_child_watch_add (pid, on_assigned_service_finished, user_data);
+}
+
+static void
+start_assigned_service (GsdSharingManager *manager,
+ AssignedServiceInfo *info)
+{
+ AssignedService *service;
+
+ if (manager->sharing_status != GSD_SHARING_STATUS_AVAILABLE)
+ return;
+
+ if (!info->system_service_running)
+ return;
+
+ service = info->service;
+
+ if (manager->is_systemd_managed) {
+ gsd_sharing_manager_start_service (manager, service->user_service_name);
+ } else {
+ g_autoptr(GDesktopAppInfo) app_info = NULL;
+ g_autoptr(GError) error = NULL;
+ guint spawn_flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH;
+
+#if GLIB_CHECK_VERSION(2, 74, 0)
+ spawn_flags |= G_SPAWN_CHILD_INHERITS_STDERR | G_SPAWN_CHILD_INHERITS_STDOUT;
+#endif
+
+ if (info->pid != 0)
+ return;
+
+ g_debug ("About to start %s directly", service->user_service_name);
+
+ app_info = g_desktop_app_info_new (service->user_service_desktop_id);
+ if (!g_desktop_app_info_launch_uris_as_manager (app_info,
+ NULL,
+ NULL,
+ spawn_flags,
+ NULL,
+ NULL,
+ on_assigned_service_started,
+ info,
+ &error)) {
+ g_warning ("Could not start %s: %s", service->user_service_desktop_id, error->message);
+ }
+ }
+}
+
+static void
+stop_assigned_service (GsdSharingManager *manager,
+ AssignedServiceInfo *info)
+{
+ AssignedService *service = info->service;
+
+ if (manager->is_systemd_managed) {
+ gsd_sharing_manager_stop_service (manager, service->user_service_name);
+ } else {
+ if (info->pid == 0)
+ return;
+
+ g_debug ("About to stop %s directly", service->user_service_name);
+
+ kill (info->pid, SIGTERM);
+ }
+}
+
+static void
+gsd_sharing_manager_sync_assigned_services (GsdSharingManager *manager)
+{
+ GList *services, *l;
+
+ services = g_hash_table_get_values (manager->assigned_services);
+
+ for (l = services; l != NULL; l = l->next) {
+ AssignedServiceInfo *info = l->data;
+
+ if (manager->sharing_status == GSD_SHARING_STATUS_AVAILABLE)
+ start_assigned_service (manager, info);
+ else
+ stop_assigned_service (manager, info);
+ }
+ g_list_free (services);
+}
+
+static void
+gsd_sharing_manager_sync_services (GsdSharingManager *manager)
+{
+ gsd_sharing_manager_sync_configurable_services (manager);
+ gsd_sharing_manager_sync_assigned_services (manager);
+}
+
#if HAVE_NETWORK_MANAGER
static void
properties_changed (GsdSharingManager *manager)
@@ -772,6 +921,58 @@ configurable_service_free (gpointer pointer)
g_free (service);
}
+static void
+assigned_service_free (gpointer pointer)
+{
+ AssignedServiceInfo *info = pointer;
+
+ g_bus_unwatch_name (info->system_bus_name_watch);
+ g_free (info);
+}
+
+static void
+on_system_bus_name_appeared (GDBusConnection *connection,
+ const char *system_bus_name,
+ const char *system_bus_name_owner,
+ gpointer user_data)
+{
+ GsdSharingManager *manager = user_data;
+ AssignedServiceInfo *info;
+
+ info = g_hash_table_lookup (manager->assigned_services, system_bus_name);
+
+ if (info == NULL)
+ return;
+
+ if (info->system_service_running)
+ return;
+
+ info->system_service_running = TRUE;
+
+ start_assigned_service (manager, info);
+}
+
+static void
+on_system_bus_name_vanished (GDBusConnection *connection,
+ const char *system_bus_name,
+ gpointer user_data)
+{
+ GsdSharingManager *manager = user_data;
+ AssignedServiceInfo *info;
+
+ info = g_hash_table_lookup (manager->assigned_services, system_bus_name);
+
+ if (info == NULL)
+ return;
+
+ if (!info->system_service_running)
+ return;
+
+ info->system_service_running = FALSE;
+
+ stop_assigned_service (manager, info);
+}
+
static void
manage_configurable_services (GsdSharingManager *manager)
{
@@ -791,10 +992,79 @@ manage_configurable_services (GsdSharingManager *manager)
}
}
+static void
+manage_assigned_services (GsdSharingManager *manager)
+{
+ size_t i;
+ int ret;
+ g_autofree char *session_id = NULL;
+ g_autofree char *session_class = NULL;
+ gboolean is_remote;
+
+ if (manager->is_systemd_managed)
+ ret = sd_uid_get_display (getuid (), &session_id);
+ else
+ ret = sd_pid_get_session (getpid (), &session_id);
+
+ if (ret != 0) {
+ g_warning ("Failed to find systemd session id: %s", g_strerror (-ret));
+ return;
+ }
+
+ ret = sd_session_get_class (session_id, &session_class);
+
+ if (ret != 0) {
+ g_warning ("Failed to find systemd session class for session %s: %s", session_id, g_strerror (-ret));
+ return;
+ }
+
+ ret = sd_session_is_remote (session_id);
+
+ if (ret < 0) {
+ g_warning ("Failed to find out if systemd session %s is remote: %s", session_id, g_strerror (-ret));
+ return;
+ }
+
+ is_remote = ret;
+
+ for (i = 0; i < G_N_ELEMENTS (assigned_services); i++) {
+ AssignedServiceInfo *info;
+ AssignedService *service;
+ const char * const *session_classes;
+
+ service = &assigned_services[i];
+
+ if (is_remote)
+ session_classes = (const char * const *) service->remote_session_classes;
+ else
+ session_classes = (const char * const *) service->local_session_classes;
+
+ if (!g_strv_contains (session_classes, session_class))
+ continue;
+
+ info = g_new0 (AssignedServiceInfo, 1);
+ info->service = service;
+
+ info->system_bus_name_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
+ service->system_bus_name,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ on_system_bus_name_appeared,
+ on_system_bus_name_vanished,
+ manager,
+ NULL);
+
+ g_hash_table_insert (manager->assigned_services, (gpointer) service->system_bus_name, info);
+ }
+}
+
static void
gsd_sharing_manager_init (GsdSharingManager *manager)
{
+ int ret;
+ g_autofree char *systemd_unit = NULL;
+
manager->configurable_services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, configurable_service_free);
+ manager->assigned_services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, assigned_service_free);
/* Default state */
manager->current_network = g_strdup ("");
@@ -802,7 +1072,15 @@ gsd_sharing_manager_init (GsdSharingManager *manager)
manager->carrier_type = g_strdup ("");
manager->sharing_status = GSD_SHARING_STATUS_OFFLINE;
+ ret = sd_pid_get_user_unit (getpid (), &systemd_unit);
+
+ if (ret < 0)
+ manager->is_systemd_managed = FALSE;
+ else
+ manager->is_systemd_managed = TRUE;
+
manage_configurable_services (manager);
+ manage_assigned_services (manager);
}
static void
@@ -820,6 +1098,7 @@ gsd_sharing_manager_finalize (GObject *object)
gsd_sharing_manager_stop (manager);
g_hash_table_unref (manager->configurable_services);
+ g_hash_table_unref (manager->assigned_services);
G_OBJECT_CLASS (gsd_sharing_manager_parent_class)->finalize (object);
}
diff --git a/plugins/sharing/meson.build b/plugins/sharing/meson.build
index 948431280..bda21608a 100644
--- a/plugins/sharing/meson.build
+++ b/plugins/sharing/meson.build
@@ -5,7 +5,8 @@ sources = files(
deps = plugins_deps + [
gio_unix_dep,
- libnotify_dep
+ libnotify_dep,
+ libsystemd_dep
]
if enable_network_manager
--
GitLab
From 8888351911e1e93faacb479f8e1ecb7e08f9b968 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 2 Nov 2023 15:02:09 -0400
Subject: [PATCH 5/5] sharing: Give assigned services 10 seconds before killing
them
It's useful to wait a bit before killing an assigned service when
the associated system service goes away.
This avoids having to tear down the user service if the system
service is just getting restarted.
This commit adds a 10 second countdown before slaying the user
service when it's system service counterpart goes down.
---
plugins/sharing/gsd-sharing-manager.c | 73 ++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/plugins/sharing/gsd-sharing-manager.c b/plugins/sharing/gsd-sharing-manager.c
index c9d890f5e..7713569f4 100644
--- a/plugins/sharing/gsd-sharing-manager.c
+++ b/plugins/sharing/gsd-sharing-manager.c
@@ -34,6 +34,8 @@
#include "gsd-sharing-manager.h"
#include "gsd-sharing-enums.h"
+#define SYSTEM_SERVICE_RESTART_TIMEOUT 10 /* seconds */
+
typedef struct {
const char *name;
GSettings *settings;
@@ -53,6 +55,7 @@ typedef struct {
gboolean system_service_running;
GPid pid;
guint child_watch_id;
+ GCancellable *cancellable;
} AssignedServiceInfo;
struct _GsdSharingManager
@@ -300,6 +303,9 @@ start_assigned_service (GsdSharingManager *manager,
if (!info->system_service_running)
return;
+ g_cancellable_cancel (info->cancellable);
+ g_clear_object (&info->cancellable);
+
service = info->service;
if (manager->is_systemd_managed) {
@@ -351,6 +357,53 @@ stop_assigned_service (GsdSharingManager *manager,
}
}
+static void
+on_done_waiting_to_stop (GsdSharingManager *manager,
+ GTask *task,
+ AssignedServiceInfo *info)
+{
+ gboolean completed;
+
+ completed = g_task_propagate_boolean (task, NULL);
+
+ if (!completed)
+ return;
+
+ stop_assigned_service (manager, info);
+}
+
+static gboolean
+on_timeout_reached (GTask *task)
+{
+ if (!g_task_return_error_if_cancelled (task))
+ g_task_return_boolean (task, TRUE);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+stop_assigned_service_after_timeout (GsdSharingManager *manager,
+ AssignedServiceInfo *info)
+{
+ g_autoptr (GTask) wait_task = NULL;
+ g_autoptr (GSource) timeout_source = NULL;
+
+ g_cancellable_cancel (info->cancellable);
+ g_set_object (&info->cancellable, g_cancellable_new ());
+
+ wait_task = g_task_new (manager,
+ info->cancellable,
+ (GAsyncReadyCallback)
+ on_done_waiting_to_stop,
+ info);
+ timeout_source = g_timeout_source_new (SYSTEM_SERVICE_RESTART_TIMEOUT * 1000);
+ g_source_set_name (timeout_source, "[gnome-settings-daemon] on_done_waiting_to_stop");
+
+ g_task_attach_source (g_steal_pointer (&wait_task),
+ timeout_source,
+ G_SOURCE_FUNC (on_timeout_reached));
+}
+
static void
gsd_sharing_manager_sync_assigned_services (GsdSharingManager *manager)
{
@@ -871,11 +924,26 @@ gsd_sharing_manager_start (GsdSharingManager *manager,
return TRUE;
}
+static void
+cancel_pending_wait_tasks (GsdSharingManager *manager)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, manager->assigned_services);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ AssignedServiceInfo *info = value;
+ g_cancellable_cancel (info->cancellable);
+ }
+}
+
void
gsd_sharing_manager_stop (GsdSharingManager *manager)
{
g_debug ("Stopping sharing manager");
+ cancel_pending_wait_tasks (manager);
+
if (manager->sharing_status == GSD_SHARING_STATUS_AVAILABLE &&
manager->connection != NULL) {
manager->sharing_status = GSD_SHARING_STATUS_OFFLINE;
@@ -926,6 +994,9 @@ assigned_service_free (gpointer pointer)
{
AssignedServiceInfo *info = pointer;
+ g_cancellable_cancel (info->cancellable);
+ g_clear_object (&info->cancellable);
+
g_bus_unwatch_name (info->system_bus_name_watch);
g_free (info);
}
@@ -970,7 +1041,7 @@ on_system_bus_name_vanished (GDBusConnection *connection,
info->system_service_running = FALSE;
- stop_assigned_service (manager, info);
+ stop_assigned_service_after_timeout (manager, info);
}
static void