[gnome-settings-daemon/benzea/spawn-in-scope] media-keys: Place spawned processes into a systemd scope



commit ce9fbdeb1aed8491e1bc6cba23adaef2455d945a
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. We
    can also set some default options for the scope, do this using a drop-in
    and default to make the process part of graphical-session.target and
    kill it after 5 seconds rather than 1min 30s.

 data/gsd-launched-override.scope.conf       |   6 ++
 data/meson.build                            |   8 +++
 meson.build                                 |   1 +
 plugins/media-keys/gsd-media-keys-manager.c | 106 ++++++++++++++++++++++++++++
 4 files changed, 121 insertions(+)
---
diff --git a/data/gsd-launched-override.scope.conf b/data/gsd-launched-override.scope.conf
new file mode 100644
index 00000000..622787ad
--- /dev/null
+++ b/data/gsd-launched-override.scope.conf
@@ -0,0 +1,6 @@
+[Unit]
+
+PartOf=graphical-session.target
+
+[Scope]
+TimeoutStopSec=5s
diff --git a/data/meson.build b/data/meson.build
index d53eb26c..2e06cfce 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -71,3 +71,11 @@ custom_target('compile-schemas',
   output: 'gschemas.compiled',
   command: [find_program('glib-compile-schemas'), meson.current_build_dir()],
   build_by_default: true)
+
+if enable_systemd
+  install_data(
+    'gsd-launched-override.scope.conf',
+    rename: 'override.conf',
+    install_dir : join_paths(systemd_userunitdir, 'gsd-launched-.scope.d')
+  )
+endif
diff --git a/meson.build b/meson.build
index 0c65f381..3c59e59d 100644
--- a/meson.build
+++ b/meson.build
@@ -113,6 +113,7 @@ if enable_systemd
   # and uncomment systemd_dep below
   systemd_userunitdir = join_paths(gsd_prefix, 'lib', 'systemd', 'user')
 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..175d55a2 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -264,6 +264,27 @@ 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) {
+                if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
+                        return;
+
+                g_warning ("%s: %s", msg, error->message);
+        }
+}
+#endif
 
 static void
 media_key_unref (MediaKey *key)
@@ -996,6 +1017,83 @@ 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);
+        gint32 pid;
+        GVariantBuilder builder;
+        const gchar *app_id;
+        g_autofree gchar *unit_name = NULL;
+        g_autoptr(GVariantDict) dict = NULL;
+
+        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;
+        }
+
+        /* Now that we have the PID, we can create start a transient
+         * scope that wraps it. */
+        g_debug ("Trying to create transient scope for PID %d\n", pid);
+
+        g_assert (priv->connection);
+
+        /* Prepare some information */
+        app_id = g_app_info_get_id (info);
+        if (app_id == NULL) {
+                app_id = "anonymous";
+        }
+        /* This needs to be unique, hopefully the pid will be enough. */
+        unit_name = g_strdup_printf ("gsd-launched-%s-%d.scope", app_id, pid);
+
+
+        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)"));
+        /* Note that futher settings are controlled using a drop-in.
+         */
+        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 +1107,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),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]