[gnome-settings-daemon/benzea/spawn-in-scope] media-keys: Place spawned processes into a systemd scope
- From: Benjamin Berg <bberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon/benzea/spawn-in-scope] media-keys: Place spawned processes into a systemd scope
- Date: Thu, 28 Nov 2019 10:27:08 +0000 (UTC)
commit f8d187eb68eae1554f508aa930c71335d121eb44
Author: Benjamin Berg <bberg redhat com>
Date: Tue Nov 26 18:20:16 2019 +0100
media-keys: Place spawned processes into a systemd scope
This means we isolate the processes from the media-keys scope itself.
The scope units are created with a gnome-launched- prefix, which allows
us to create a GNOME wide drop-in to set defaults.
If systemd support is disabled, or we are not running on a systemd
session, then the code will do nothing.
meson.build | 5 ++
plugins/media-keys/gsd-media-keys-manager.c | 130 ++++++++++++++++++++++++++++
plugins/media-keys/meson.build | 3 +-
3 files changed, 137 insertions(+), 1 deletion(-)
---
diff --git a/meson.build b/meson.build
index 0c65f381..400b285a 100644
--- a/meson.build
+++ b/meson.build
@@ -104,7 +104,9 @@ x11_dep = dependency('x11')
enable_systemd = get_option('systemd')
if enable_systemd
+ libsystemd_dep = dependency('libsystemd')
systemd_dep = dependency('systemd', required: false)
+ assert(libsystemd_dep.found(), 'Systemd support explicitly required, but libsystemd not found')
assert(systemd_dep.found(), 'Systemd support explicitly required, but systemd not found')
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
@@ -112,7 +114,10 @@ if enable_systemd
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir')
# and uncomment systemd_dep below
systemd_userunitdir = join_paths(gsd_prefix, 'lib', 'systemd', 'user')
+else
+ libsystemd_dep = []
endif
+config_h.set10('HAVE_SYSTEMD', enable_systemd)
m_dep = cc.find_library('m')
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 4e167c86..23de816c 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -46,6 +46,10 @@
#include <gudev/gudev.h>
#endif
+#if HAVE_SYSTEMD
+#include <systemd/sd-login.h>
+#endif
+
#include "gsd-settings-migrate.h"
#include "mpris-controller.h"
@@ -264,6 +268,23 @@ G_DEFINE_TYPE_WITH_PRIVATE (GsdMediaKeysManager, gsd_media_keys_manager, G_TYPE_
static gpointer manager_object = NULL;
+#if HAVE_SYSTEMD
+static void
+dbus_call_log_error (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) result;
+ g_autoptr(GError) error = NULL;
+ const gchar *msg = user_data;
+
+ result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+ if (error)
+ g_warning ("%s: %s", msg, error->message);
+}
+#endif
static void
media_key_unref (MediaKey *key)
@@ -996,6 +1017,107 @@ init_kbd (GsdMediaKeysManager *manager)
gnome_settings_profile_end (NULL);
}
+#if HAVE_SYSTEMD
+static void
+app_launched_cb (GAppLaunchContext *context,
+ GAppInfo *info,
+ GVariant *platform_data,
+ gpointer user_data)
+{
+ GsdMediaKeysManager *manager = GSD_MEDIA_KEYS_MANAGER (user_data);
+ GsdMediaKeysManagerPrivate *priv = GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager);
+ const char *valid_chars =
+ "-._1234567890"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ gint32 pid;
+ GVariantBuilder builder;
+ const gchar *app_id;
+ g_autofree gchar *mangled_app_id = NULL;
+ g_autofree gchar *unit_name = NULL;
+ g_autofree gchar *own_unit = NULL;
+ g_autoptr(GVariantDict) dict = NULL;
+ gint res;
+
+ g_return_if_fail (platform_data != NULL);
+
+ dict = g_variant_dict_new (platform_data);
+
+ g_return_if_fail (g_variant_dict_contains (dict, "pid"));
+
+ if (!g_variant_dict_lookup (dict, "pid", "i", &pid)) {
+ g_critical ("Could not unpack pid from platform data.");
+ return;
+ }
+
+ /* We cannot do anything if this process is not managed by the
+ * systemd user instance. */
+ res = sd_pid_get_user_unit (getpid (), &own_unit);
+ if (res == -ENODATA) {
+ g_debug ("Not systemd managed, will not move PID %d into transient scope\n", pid);
+ return;
+ }
+ if (res < 0) {
+ g_warning ("Error retrieving user unit for own PID: %i", -res);
+ return;
+ }
+
+ g_debug ("Trying to create transient scope for PID %d\n", pid);
+
+ g_assert (priv->connection);
+
+ /* Create a nice and (mangled) name to embed into the unit */
+ app_id = g_app_info_get_id (info);
+ if (app_id == NULL)
+ app_id = g_app_info_get_executable (info);
+ if (app_id == NULL)
+ app_id = "anonymous";
+
+ if (app_id[0] == '/')
+ app_id++;
+
+ mangled_app_id = g_str_to_ascii (app_id, "C");
+ g_strdelimit (mangled_app_id, "/", '-');
+ g_strcanon (mangled_app_id, valid_chars, '_');
+
+ /* This needs to be unique, hopefully the pid will be enough. */
+ unit_name = g_strdup_printf ("gnome-launched-%s-%d.scope", mangled_app_id, pid);
+
+ /* Build arguments */
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
+ g_variant_builder_add (&builder, "s", unit_name);
+ g_variant_builder_add (&builder, "s", "fail");
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sv)"));
+ g_variant_builder_add (&builder,
+ "(sv)",
+ "Description",
+ g_variant_new_string ("Application launched by gsd-media-keys"));
+ g_variant_builder_add (&builder,
+ "(sv)",
+ "PIDs",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &pid, 1, 4));
+
+ g_variant_builder_close (&builder);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sa(sv))"));
+ g_variant_builder_close (&builder);
+
+ g_dbus_connection_call (priv->connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit",
+ g_variant_builder_end (&builder),
+ G_VARIANT_TYPE ("(o)"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ 1000,
+ NULL,
+ dbus_call_log_error,
+ "Failed to create transient unit");
+}
+#endif
+
static void
launch_app (GsdMediaKeysManager *manager,
GAppInfo *app_info,
@@ -1009,6 +1131,14 @@ launch_app (GsdMediaKeysManager *manager,
gdk_app_launch_context_set_timestamp (launch_context, timestamp);
set_launch_context_env (manager, G_APP_LAUNCH_CONTEXT (launch_context));
+#if HAVE_SYSTEMD
+ g_signal_connect_object (launch_context,
+ "launched",
+ G_CALLBACK (app_launched_cb),
+ manager,
+ 0);
+#endif
+
if (!g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error)) {
g_warning ("Could not launch '%s': %s",
g_app_info_get_commandline (app_info),
diff --git a/plugins/media-keys/meson.build b/plugins/media-keys/meson.build
index e6c1d2ac..d233b5e8 100644
--- a/plugins/media-keys/meson.build
+++ b/plugins/media-keys/meson.build
@@ -30,7 +30,8 @@ deps = plugins_deps + [
libgvc_dep,
libpulse_mainloop_glib_dep,
m_dep,
- upower_glib_dep
+ upower_glib_dep,
+ libsystemd_dep
]
if enable_gudev
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]