public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Benjamin Berg <bberg@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/glib2] cve-2026-58016-f44: Add patches to move applications into systemd scopes
Date: Tue, 11 Aug 2026 10:37:16 GMT	[thread overview]
Message-ID: <178644463687.1.4469519533191010786.rpms-glib2-56c964dd927e@fedoraproject.org> (raw)

            A new commit has been pushed.

            Repo   : rpms/glib2
            Branch : cve-2026-58016-f44
            Commit : 56c964dd927ec16cf21a972f19a6a9f972f94916
            Author : Benjamin Berg <bberg@redhat.com>
            Date   : 2021-02-09T13:29:16+01:00
            Stats  : +878/-1 in 5 file(s)
            URL    : https://src.fedoraproject.org/rpms/glib2/c/56c964dd927ec16cf21a972f19a6a9f972f94916?branch=cve-2026-58016-f44

            Log:
            Add patches to move applications into systemd scopes

Doing this means we get more applications into their own cgroup/systemd
unit. This is important for systemd-oomd to work properly, as it tends
to work on a cgroup level.

---
diff --git a/0001-tests-Iterate-mainloop-during-launch-test.patch b/0001-tests-Iterate-mainloop-during-launch-test.patch
new file mode 100644
index 0000000..a6c4076
--- /dev/null
+++ b/0001-tests-Iterate-mainloop-during-launch-test.patch
@@ -0,0 +1,30 @@
+From 156ddbc49bc432262fd022efd9831f789fa32e64 Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Fri, 23 Oct 2020 18:20:01 +0200
+Subject: [PATCH 1/4] tests: Iterate mainloop during launch test
+
+When launching an application, we wait for the DBus response from
+systemd before executing the binary. Because of this the main loop needs
+to be iterated for spawning to completed and the file to be created.
+
+Without this the test will time out if GLib was able to connect to the
+session bus.
+---
+ gio/tests/desktop-app-info.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c
+index 98601de4f..fb87bf2c2 100644
+--- a/gio/tests/desktop-app-info.c
++++ b/gio/tests/desktop-app-info.c
+@@ -334,6 +334,7 @@ wait_for_file (const gchar *want_this,
+    */
+   while (access (want_this, F_OK) != 0)
+     {
++      g_main_context_iteration (NULL, FALSE);
+       g_usleep (100000); /* 100ms */
+       g_assert_cmpuint (retries, >, 0);
+       retries--;
+-- 
+2.29.2
+

diff --git a/0002-gdesktopappinfo-Move-launched-applications-into-tran.patch b/0002-gdesktopappinfo-Move-launched-applications-into-tran.patch
new file mode 100644
index 0000000..6899c16
--- /dev/null
+++ b/0002-gdesktopappinfo-Move-launched-applications-into-tran.patch
@@ -0,0 +1,389 @@
+From 1e4e58a73f12cded2d67f58571ea42906f3c3f94 Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Mon, 27 Jul 2020 22:22:32 +0200
+Subject: [PATCH 2/4] gdesktopappinfo: Move launched applications into
+ transient scope
+
+Try to move the spawned executable into its own systemd scope. To avoid
+possible race conditions and ensure proper accounting, we delay the
+execution of the real command until after the DBus call to systemd has
+finished.
+
+From the two approaches we can take here, this is better in the sense
+that we have a child that the API consumer can watch. API consumers
+should not be doing this, however, gnome-session needs to watch children
+during session startup. Until gnome-session is fixed, we will not be
+able to change this.
+
+The alternative approach is to delegate launching itself to systemd by
+creating a transient .service unit instead. This is cleaner and has e.g.
+the advantage that systemd will take care of log redirection and similar
+issues.
+
+Note that this patch is incomplete. The DBus call is done in a "fire and
+forget" manner, which is fine in most cases, but means that "gio open"
+will fail to move the child into the new scope as gio quits before the
+DBus call finishes.
+---
+ gio/gdesktopappinfo.c | 263 ++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 228 insertions(+), 35 deletions(-)
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index 1a4b97918..2f1e6828b 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -2730,6 +2730,148 @@ notify_desktop_launch (GDBusConnection  *session_bus,
+ 
+ #define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH)
+ 
++#if defined(__linux__) && !defined(__BIONIC__)
++typedef struct {
++  int pipe[2];
++  GSpawnChildSetupFunc user_setup;
++  gpointer             user_setup_data;
++} SpawnWrapperData;
++
++static void
++launch_uris_with_spawn_delay_exec (gpointer user_data)
++{
++  SpawnWrapperData *data = user_data;
++
++  /* Clear CLOEXEC again, as that was set due to
++   * G_SPAWN_LEAVE_DESCRIPTORS_OPEN not being set. */
++  fcntl (data->pipe[0], F_SETFD, 0);
++
++  /* No need to close read side, we have CLOEXEC set. */
++
++  if (data->user_setup)
++    data->user_setup (data->user_setup_data);
++}
++
++static gchar *
++systemd_unit_name_escape (const gchar *in)
++{
++  /* Adapted from systemd source */
++  GString * const str = g_string_sized_new (strlen (in));
++
++  for (; *in; in++)
++    {
++      if (g_ascii_isalnum (*in) || *in == ':' || *in == '_' || *in == '.')
++        g_string_append_c (str, *in);
++      else
++        g_string_append_printf (str, "\\x%02x", *in);
++    }
++  return g_string_free (str, FALSE);
++}
++
++static void
++create_systemd_scope (GDBusConnection    *session_bus,
++                      GDesktopAppInfo    *info,
++                      gint                pid,
++                      GAsyncReadyCallback callback,
++                      gpointer            user_data)
++{
++  GVariantBuilder builder;
++  const char *app_name = g_get_application_name ();
++  char *appid = NULL;
++  char *appid_escaped = NULL;
++  char *snid_escaped = NULL;
++  char *unit_name = NULL;
++
++  /* In this order:
++   *  1. Actual application ID from file
++   *  2. Stripping the .desktop from the desktop ID
++   *  3. Fall back to using the binary name
++   */
++  if (info->app_id)
++    appid = g_strdup (info->app_id);
++  else if (info->desktop_id && g_str_has_suffix (info->desktop_id, ".desktop"))
++    appid = g_strndup (info->desktop_id, strlen (info->desktop_id) - 8);
++  else
++    appid = g_path_get_basename (info->binary);
++
++  appid_escaped = systemd_unit_name_escape (appid);
++
++  /* Generate a name conforming to
++   *   https://systemd.io/DESKTOP_ENVIRONMENTS/
++   * We use the PID to disambiguate, as that should be unique enough.
++   */
++  unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, 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)"));
++
++  /* Add a generic human readable description, can be changed at will. */
++  if (app_name)
++    g_variant_builder_add (&builder,
++                           "(sv)",
++                           "Description",
++                           g_variant_new_take_string (g_strdup_printf ("Application launched by %s",
++                                                                       app_name)));
++  g_variant_builder_add (&builder,
++                         "(sv)",
++                         "PIDs",
++                          g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &pid, 1, 4));
++  /* Default to let systemd garbage collect failed applications we launched. */
++  g_variant_builder_add (&builder,
++                         "(sv)",
++                         "CollectMode",
++                          g_variant_new_string ("inactive-or-failed"));
++
++  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 (session_bus,
++                          "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,
++                          callback,
++                          user_data);
++
++  g_free (appid);
++  g_free (appid_escaped);
++  g_free (snid_escaped);
++  g_free (unit_name);
++}
++
++static void
++systemd_scope_created_cb (GObject      *object,
++                          GAsyncResult *result,
++                          gpointer      user_data)
++{
++  GVariant *res = NULL;
++  GError *error = NULL;
++
++  res = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error);
++  if (error != NULL)
++    {
++      g_debug ("Failed to move new child into scope: %s", error->message);
++      g_error_free (error);
++    }
++
++  /* Unblock the waiting wrapper binary. */
++  close (GPOINTER_TO_INT (user_data));
++
++  if (res)
++    g_variant_unref (res);
++}
++#endif
++
+ static gboolean
+ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+                                            GDBusConnection            *session_bus,
+@@ -2750,13 +2892,14 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+   GList *old_uris;
+   GList *dup_uris;
+ 
+-  char **argv, **envp;
++  GStrv argv = NULL, envp = NULL;
++  GStrv wrapped_argv = NULL;
++  GList *launched_uris = NULL;
++  char *sn_id = NULL;
+   int argc;
+ 
+   g_return_val_if_fail (info != NULL, FALSE);
+ 
+-  argv = NULL;
+-
+   if (launch_context)
+     envp = g_app_launch_context_get_environment (launch_context);
+   else
+@@ -2770,27 +2913,19 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+   do
+     {
+       GPid pid;
+-      GList *launched_uris;
+       GList *iter;
+-      char *sn_id = NULL;
+-      char **wrapped_argv;
+       int i;
+-      gsize j;
+-      const gchar * const wrapper_argv[] =
+-        {
+-          "/bin/sh",
+-          "-e",
+-          "-u",
+-          "-c", "export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"",
+-          "sh",  /* argv[0] for sh */
+-        };
++#if defined(__linux__) && !defined(__BIONIC__)
++      SpawnWrapperData wrapper_data;
++#endif
++      GSpawnChildSetupFunc setup = user_setup;
++      gpointer             setup_data = user_setup_data;
+ 
+       old_uris = dup_uris;
+       if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error))
+-        goto out;
++        return FALSE;
+ 
+       /* Get the subset of URIs we're launching with this process */
+-      launched_uris = NULL;
+       for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next)
+         launched_uris = g_list_prepend (launched_uris, iter->data);
+       launched_uris = g_list_reverse (launched_uris);
+@@ -2799,7 +2934,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+         {
+           g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                                _("Unable to find terminal required for application"));
+-          goto out;
++          return FALSE;
+         }
+ 
+       if (info->filename)
+@@ -2808,7 +2943,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+                                  info->filename,
+                                  TRUE);
+ 
+-      sn_id = NULL;
+       if (launch_context)
+         {
+           GList *launched_files = create_files_for_uris (launched_uris);
+@@ -2837,38 +2971,96 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+        * with a wrapper program (grep the GLib git history for
+        * `gio-launch-desktop` for an example of this which could be
+        * resurrected). */
+-      wrapped_argv = g_new (char *, argc + G_N_ELEMENTS (wrapper_argv) + 1);
++      wrapped_argv = g_new (char *, argc + 6 + 1);
++
++      wrapped_argv[0] = g_strdup ("/bin/sh");
++      wrapped_argv[1] = g_strdup ("-e");
++      wrapped_argv[2] = g_strdup ("-u");
++      wrapped_argv[3] = g_strdup ("-c");
++      /* argument 4 is filled in below */
++      wrapped_argv[5] = g_strdup ("sh");
+ 
+-      for (j = 0; j < G_N_ELEMENTS (wrapper_argv); j++)
+-        wrapped_argv[j] = g_strdup (wrapper_argv[j]);
+       for (i = 0; i < argc; i++)
+-        wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = g_steal_pointer (&argv[i]);
++        wrapped_argv[i + 6] = g_steal_pointer (&argv[i]);
+ 
+-      wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = NULL;
+-      g_free (argv);
+-      argv = NULL;
++      wrapped_argv[i + 6] = NULL;
++      g_clear_pointer (&argv, g_free);
++
++#if defined(__linux__) && !defined(__BIONIC__)
++      /* Create pipes, if we use a setup func, then set cloexec,
++       * otherwise our wrapper script will close both sides. */
++      if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL))
++        {
++          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                               _("Unable to create pipe for systemd synchronization"));
++          return FALSE;
++        }
++
++      /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */
++      fcntl (wrapper_data.pipe[1], F_SETFD, FD_CLOEXEC);
++
++      if (!(spawn_flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
++        {
++          /* In this case, we use a setup function (which could probably also
++           * overwrite envp to set GIO_LAUNCHED_DESKTOP_FILE_PID).
++           *
++           * Note that this does not incur an additional cost because
++           * G_SPAWN_LEAVE_DESCRIPTOR_OPEN must be set in order to use
++           * posix_spawn. */
++          wrapper_data.user_setup = setup;
++          wrapper_data.user_setup_data = setup_data;
++
++          setup = launch_uris_with_spawn_delay_exec;
++          setup_data = &wrapper_data;
++        }
++
++      wrapped_argv[4] = g_strdup_printf ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; cat <&%1$d; exec \"$@\" %1$d<&-",
++                                         wrapper_data.pipe[0]);
++#else
++      wrapped_argv[4] = g_strdup ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"");
++#endif
+ 
+       if (!g_spawn_async_with_fds (info->path,
+                                    wrapped_argv,
+                                    envp,
+                                    spawn_flags,
+-                                   user_setup,
+-                                   user_setup_data,
++                                   setup,
++                                   setup_data,
+                                    &pid,
+                                    stdin_fd,
+                                    stdout_fd,
+                                    stderr_fd,
+                                    error))
+         {
++#if defined(__linux__) && !defined(__BIONIC__)
++          close (wrapper_data.pipe[0]);
++          close (wrapper_data.pipe[1]);
++#endif
++
+           if (sn_id)
+             g_app_launch_context_launch_failed (launch_context, sn_id);
+ 
+           g_free (sn_id);
+           g_list_free (launched_uris);
+ 
+-          goto out;
++          goto err;
+         }
+ 
++#if defined(__linux__) && !defined(__BIONIC__)
++      /* We close write side asynchronously later on when the dbus call
++       * to systemd finishes. */
++      close (wrapper_data.pipe[0]);
++
++      if (session_bus)
++        create_systemd_scope (session_bus,
++                              info,
++                              pid,
++                              systemd_scope_created_cb,
++                              GINT_TO_POINTER (wrapper_data.pipe[1]));
++      else
++        close (wrapper_data.pipe[1]);
++#endif
++
+       if (pid_callback != NULL)
+         pid_callback (info, pid, pid_callback_data);
+ 
+@@ -2893,19 +3085,20 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+                              sn_id,
+                              launched_uris);
+ 
+-      g_free (sn_id);
+-      g_list_free (launched_uris);
+-
+-      g_strfreev (wrapped_argv);
+-      wrapped_argv = NULL;
++      g_clear_pointer (&sn_id, g_free);
++      g_clear_pointer (&launched_uris, g_list_free);
++      g_clear_pointer (&wrapped_argv, g_strfreev);
+     }
+   while (dup_uris != NULL);
+ 
+   completed = TRUE;
+ 
+- out:
++out:
+   g_strfreev (argv);
+   g_strfreev (envp);
++  g_clear_pointer (&wrapped_argv, g_strfreev);
++  g_list_free (launched_uris);
++  g_free (sn_id);
+ 
+   return completed;
+ }
+-- 
+2.29.2
+

diff --git a/0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch b/0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch
new file mode 100644
index 0000000..cf24b8d
--- /dev/null
+++ b/0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch
@@ -0,0 +1,391 @@
+From d13a15a0c569348cfd5aa207ee219b73117e938c Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Tue, 28 Jul 2020 12:11:13 +0200
+Subject: [PATCH 3/4] gdesktopappinfo: Handle task completion from spawn
+ function
+
+This allows delaying the return of the task until all dbus calls (in
+particular the ones to setup the scope) have finished.
+
+This fixes the behaviour of the previous commit which would not
+correctly move the process into the scope if the application exited
+right after the task returned.
+---
+ gio/gdesktopappinfo.c | 214 +++++++++++++++++++++++++++++-------------
+ 1 file changed, 147 insertions(+), 67 deletions(-)
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index 2f1e6828b..743027422 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -2849,11 +2849,17 @@ create_systemd_scope (GDBusConnection    *session_bus,
+   g_free (unit_name);
+ }
+ 
++typedef struct {
++  GTask *task;
++  int fd;
++} ScopeCreatedData;
++
+ static void
+ systemd_scope_created_cb (GObject      *object,
+                           GAsyncResult *result,
+                           gpointer      user_data)
+ {
++  ScopeCreatedData *data = user_data;
+   GVariant *res = NULL;
+   GError *error = NULL;
+ 
+@@ -2865,13 +2871,47 @@ systemd_scope_created_cb (GObject      *object,
+     }
+ 
+   /* Unblock the waiting wrapper binary. */
+-  close (GPOINTER_TO_INT (user_data));
++
++  close (data->fd);
++
++  if (data->task)
++    {
++      gint pending;
++      pending = GPOINTER_TO_INT (g_task_get_task_data (data->task));
++      pending -= 1;
++      g_task_set_task_data (data->task, GINT_TO_POINTER (pending), NULL);
++
++      if (pending == 0 && !g_task_get_completed (data->task))
++        g_task_return_boolean (data->task, TRUE);
++    }
+ 
+   if (res)
+     g_variant_unref (res);
++  g_clear_object (&data->task);
++  g_free (data);
+ }
+ #endif
+ 
++static void
++launch_uris_with_spawn_flush_cb (GObject      *object,
++                                 GAsyncResult *result,
++                                 gpointer      user_data)
++{
++  GTask *task = G_TASK (user_data);
++  gint pending;
++
++  g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL);
++
++  pending = GPOINTER_TO_INT (g_task_get_task_data (task));
++  pending -= 1;
++  g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
++
++  if (pending == 0 && !g_task_get_completed (task))
++    g_task_return_boolean (task, TRUE);
++
++  g_object_unref (task);
++}
++
+ static gboolean
+ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+                                            GDBusConnection            *session_bus,
+@@ -2886,9 +2926,10 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+                                            gint                        stdin_fd,
+                                            gint                        stdout_fd,
+                                            gint                        stderr_fd,
+-                                           GError                    **error)
++                                           GTask                      *task,
++                                           GError                    **error_out)
+ {
+-  gboolean completed = FALSE;
++  GError *error = NULL;
+   GList *old_uris;
+   GList *dup_uris;
+ 
+@@ -2898,8 +2939,15 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+   char *sn_id = NULL;
+   int argc;
+ 
++  /* We may get a task to report back on or an error. But never both. */
++  g_assert (!(task && error_out));
+   g_return_val_if_fail (info != NULL, FALSE);
+ 
++  /* Surrounding code must not have set any data on the task
++   * (it is cleared before calling this function). */
++  if (session_bus && task)
++    g_assert (g_task_get_task_data (task) == NULL);
++
+   if (launch_context)
+     envp = g_app_launch_context_get_environment (launch_context);
+   else
+@@ -2922,8 +2970,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+       gpointer             setup_data = user_setup_data;
+ 
+       old_uris = dup_uris;
+-      if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error))
+-        return FALSE;
++      if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, &error))
++        goto out;
+ 
+       /* Get the subset of URIs we're launching with this process */
+       for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next)
+@@ -2932,9 +2980,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+ 
+       if (info->terminal && !prepend_terminal_to_vector (&argc, &argv))
+         {
+-          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+-                               _("Unable to find terminal required for application"));
+-          return FALSE;
++          error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
++                                       _("Unable to find terminal required for application"));
++          goto out;
+         }
+ 
+       if (info->filename)
+@@ -2991,9 +3039,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+        * otherwise our wrapper script will close both sides. */
+       if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL))
+         {
+-          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+-                               _("Unable to create pipe for systemd synchronization"));
+-          return FALSE;
++          error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
++                                       _("Unable to create pipe for systemd synchronization"));
++          goto out;
+         }
+ 
+       /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */
+@@ -3030,7 +3078,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+                                    stdin_fd,
+                                    stdout_fd,
+                                    stderr_fd,
+-                                   error))
++                                   &error))
+         {
+ #if defined(__linux__) && !defined(__BIONIC__)
+           close (wrapper_data.pipe[0]);
+@@ -3043,7 +3091,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+           g_free (sn_id);
+           g_list_free (launched_uris);
+ 
+-          goto err;
++          goto out;
+         }
+ 
+ #if defined(__linux__) && !defined(__BIONIC__)
+@@ -3052,11 +3100,29 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+       close (wrapper_data.pipe[0]);
+ 
+       if (session_bus)
+-        create_systemd_scope (session_bus,
+-                              info,
+-                              pid,
+-                              systemd_scope_created_cb,
+-                              GINT_TO_POINTER (wrapper_data.pipe[1]));
++        {
++          ScopeCreatedData *data;
++
++          data = g_new0 (ScopeCreatedData, 1);
++
++          if (task)
++            {
++              gint pending;
++              pending = GPOINTER_TO_INT (g_task_get_task_data (task));
++              pending += 1;
++              g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
++
++              data->task = g_object_ref (task);
++            }
++
++          data->fd = wrapper_data.pipe[1];
++
++          create_systemd_scope (session_bus,
++                                info,
++                                pid,
++                                systemd_scope_created_cb,
++                                data);
++        }
+       else
+         close (wrapper_data.pipe[1]);
+ #endif
+@@ -3091,8 +3157,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo            *info,
+     }
+   while (dup_uris != NULL);
+ 
+-  completed = TRUE;
+-
+ out:
+   g_strfreev (argv);
+   g_strfreev (envp);
+@@ -3100,7 +3164,52 @@ out:
+   g_list_free (launched_uris);
+   g_free (sn_id);
+ 
+-  return completed;
++  if (!error)
++    {
++      if (session_bus && task)
++        {
++          GCancellable *cancellable = g_task_get_cancellable (task);
++          gint pending;
++          pending = GPOINTER_TO_INT (g_task_get_task_data (task));
++          pending += 1;
++          g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
++
++          /* FIXME: The D-Bus message from the notify_desktop_launch() function
++           * can be still lost even if flush is called later. See:
++           * https://gitlab.freedesktop.org/dbus/dbus/issues/72
++           */
++          g_dbus_connection_flush (session_bus,
++                                   cancellable,
++                                   launch_uris_with_spawn_flush_cb,
++                                   g_steal_pointer (&task));
++        }
++      else if (session_bus)
++        {
++          /* No task available. */
++          g_dbus_connection_flush (session_bus,
++                                   NULL,
++                                   NULL,
++                                   NULL);
++        }
++      else if (task)
++        {
++          /* Return the given task. */
++          g_task_return_boolean (task, TRUE);
++          g_object_unref (task);
++        }
++    }
++  else
++    {
++      if (task)
++        {
++          g_task_return_error (task, error);
++          g_object_unref (task);
++        }
++      else
++        g_propagate_error (error_out, error);
++    }
++
++  return !error;
+ }
+ 
+ static gchar *
+@@ -3249,17 +3358,9 @@ g_desktop_app_info_launch_uris_internal (GAppInfo                   *appinfo,
+     success = g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec, uris, launch_context,
+                                                          spawn_flags, user_setup, user_setup_data,
+                                                          pid_callback, pid_callback_data,
+-                                                         stdin_fd, stdout_fd, stderr_fd, error);
++                                                         stdin_fd, stdout_fd, stderr_fd, NULL, error);
+ 
+-  if (session_bus != NULL)
+-    {
+-      /* This asynchronous flush holds a reference until it completes,
+-       * which ensures that the following unref won't immediately kill
+-       * the connection if we were the initial owner.
+-       */
+-      g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
+-      g_object_unref (session_bus);
+-    }
++  g_clear_object (&session_bus);
+ 
+   return success;
+ }
+@@ -3313,18 +3414,6 @@ launch_uris_with_dbus_cb (GObject      *object,
+   g_object_unref (task);
+ }
+ 
+-static void
+-launch_uris_flush_cb (GObject      *object,
+-                      GAsyncResult *result,
+-                      gpointer      user_data)
+-{
+-  GTask *task = G_TASK (user_data);
+-
+-  g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL);
+-  g_task_return_boolean (task, TRUE);
+-  g_object_unref (task);
+-}
+-
+ static void
+ launch_uris_bus_get_cb (GObject      *object,
+                         GAsyncResult *result,
+@@ -3333,12 +3422,20 @@ launch_uris_bus_get_cb (GObject      *object,
+   GTask *task = G_TASK (user_data);
+   GDesktopAppInfo *info = G_DESKTOP_APP_INFO (g_task_get_source_object (task));
+   LaunchUrisData *data = g_task_get_task_data (task);
++  LaunchUrisData *data_copy = NULL;
+   GCancellable *cancellable = g_task_get_cancellable (task);
+   GDBusConnection *session_bus;
+-  GError *error = NULL;
+ 
+   session_bus = g_bus_get_finish (result, NULL);
+ 
++  data_copy = g_new0 (LaunchUrisData, 1);
++  data_copy->appinfo = g_steal_pointer (&data->appinfo);
++  data_copy->uris = g_steal_pointer (&data->uris);
++  data_copy->context = g_steal_pointer (&data->context);
++
++  /* Allow other data to be attached to the task. */
++  g_task_set_task_data (task, NULL, NULL);
++
+   if (session_bus && info->app_id)
+     {
+       /* FIXME: The g_document_portal_add_documents() function, which is called
+@@ -3346,34 +3443,21 @@ launch_uris_bus_get_cb (GObject      *object,
+        * uses blocking calls.
+        */
+       g_desktop_app_info_launch_uris_with_dbus (info, session_bus,
+-                                                data->uris, data->context,
++                                                data_copy->uris, data_copy->context,
+                                                 cancellable,
+                                                 launch_uris_with_dbus_cb,
+                                                 g_steal_pointer (&task));
+     }
+   else
+     {
+-      /* FIXME: The D-Bus message from the notify_desktop_launch() function
+-       * can be still lost even if flush is called later. See:
+-       * https://gitlab.freedesktop.org/dbus/dbus/issues/72
+-       */
+       g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec,
+-                                                 data->uris, data->context,
++                                                 data_copy->uris, data_copy->context,
+                                                  _SPAWN_FLAGS_DEFAULT, NULL,
+                                                  NULL, NULL, NULL, -1, -1, -1,
+-                                                 &error);
+-      if (error != NULL)
+-        {
+-          g_task_return_error (task, g_steal_pointer (&error));
+-          g_object_unref (task);
+-        }
+-      else
+-        g_dbus_connection_flush (session_bus,
+-                                 cancellable,
+-                                 launch_uris_flush_cb,
+-                                 g_steal_pointer (&task));
++                                                 g_steal_pointer (&task), NULL);
+     }
+ 
++  launch_uris_data_free (data_copy);
+   g_clear_object (&session_bus);
+ }
+ 
+@@ -5189,16 +5273,12 @@ g_desktop_app_info_launch_action (GDesktopAppInfo   *info,
+       if (exec_line)
+         g_desktop_app_info_launch_uris_with_spawn (info, session_bus, exec_line, NULL, launch_context,
+                                                    _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL,
+-                                                   -1, -1, -1, NULL);
++                                                   -1, -1, -1, NULL, NULL);
+ 
+       g_free (exec_line);
+     }
+ 
+-  if (session_bus != NULL)
+-    {
+-      g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
+-      g_object_unref (session_bus);
+-    }
++  g_clear_object (&session_bus);
+ }
+ /* Epilogue {{{1 */
+ 
+-- 
+2.29.2
+

diff --git a/0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch b/0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch
new file mode 100644
index 0000000..15a8edb
--- /dev/null
+++ b/0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch
@@ -0,0 +1,56 @@
+From 67d764ecd52b4f7e972eb355a41cd90b8dcca10c Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Thu, 17 Sep 2020 17:35:58 +0200
+Subject: [PATCH 4/4] gdesktopappinfo: Add SourcePath= to transient systemd
+ units
+
+systemd allows setting a SourcePath= which shows the file that the unit
+has been generated from. KDE is starting to set this and it seems like a
+good idea, so do the same here.
+
+See https://invent.kde.org/frameworks/kio/-/merge_requests/124
+---
+ gio/gdesktopappinfo.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index 743027422..1b763b76c 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -2777,6 +2777,7 @@ create_systemd_scope (GDBusConnection    *session_bus,
+ {
+   GVariantBuilder builder;
+   const char *app_name = g_get_application_name ();
++  const char *source_path = NULL;
+   char *appid = NULL;
+   char *appid_escaped = NULL;
+   char *snid_escaped = NULL;
+@@ -2802,6 +2803,8 @@ create_systemd_scope (GDBusConnection    *session_bus,
+    */
+   unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid);
+ 
++  source_path = g_desktop_app_info_get_filename (info);
++
+   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");
+@@ -2815,6 +2818,16 @@ create_systemd_scope (GDBusConnection    *session_bus,
+                            "Description",
+                            g_variant_new_take_string (g_strdup_printf ("Application launched by %s",
+                                                                        app_name)));
++
++  /* If we have a .desktop file, document that the scope has been "generated"
++   * from it.
++   */
++  if (source_path && g_utf8_validate (source_path, -1, NULL))
++    g_variant_builder_add (&builder,
++                           "(sv)",
++                           "SourcePath",
++                           g_variant_new_string (source_path));
++
+   g_variant_builder_add (&builder,
+                          "(sv)",
+                          "PIDs",
+-- 
+2.29.2
+

diff --git a/glib2.spec b/glib2.spec
index 7211ebf..4b7153e 100644
--- a/glib2.spec
+++ b/glib2.spec
@@ -1,6 +1,6 @@
 Name: glib2
 Version: 2.67.3
-Release: 1%{?dist}
+Release: 2%{?dist}
 Summary: A library of handy utility functions
 
 License: LGPLv2+
@@ -46,6 +46,14 @@ Obsoletes: glib2-fam < 2.67.1-3
 # glib 2.59.0 hash table changes broke older gcr versions / password prompts in gnome-shell
 Conflicts: gcr < 3.28.1
 
+# Add patches to move applications into systemd scopes in compliance with
+# https://systemd.io/DESKTOP_ENVIRONMENTS/
+# Proposed upstream at https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1596
+Patch001: 0001-tests-Iterate-mainloop-during-launch-test.patch
+Patch002: 0002-gdesktopappinfo-Move-launched-applications-into-tran.patch
+Patch003: 0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch
+Patch004: 0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch
+
 %description
 GLib is the low-level core library that forms the basis for projects
 such as GTK+ and GNOME. It provides data structure handling for C,
@@ -230,6 +238,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
 %{_datadir}/installed-tests
 
 %changelog
+* Tue Feb 09 2021 Benjamin Berg <bberg@redhat.com> - 2.67.3-2
+- Add patches to move applications into systemd scopes
+
 * Thu Feb 04 2021 Kalev Lember <klember@redhat.com> - 2.67.3-1
 - Update to 2.67.3
 - Fix gtk-doc directory ownership

                 reply	other threads:[~2026-08-11 10:37 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178644463687.1.4469519533191010786.rpms-glib2-56c964dd927e@fedoraproject.org \
    --to=bberg@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox