From afb420636a57932b505011c783b189a36ea69e24 Mon Sep 17 00:00:00 2001 From: DistroBaker Date: Tue, 9 Feb 2021 13:26:50 +0000 Subject: [PATCH] Merged update from upstream sources This is an automated DistroBaker update from upstream sources. If you do not know what this is about or would like to opt out, contact the OSCI team. Source: https://src.fedoraproject.org/rpms/glib2.git#56c964dd927ec16cf21a972f19a6a9f972f94916 --- ...-Iterate-mainloop-during-launch-test.patch | 30 ++ ...Move-launched-applications-into-tran.patch | 389 +++++++++++++++++ ...Handle-task-completion-from-spawn-fu.patch | 391 ++++++++++++++++++ ...Add-SourcePath-to-transient-systemd-.patch | 56 +++ glib2.spec | 13 +- 5 files changed, 878 insertions(+), 1 deletion(-) create mode 100644 0001-tests-Iterate-mainloop-during-launch-test.patch create mode 100644 0002-gdesktopappinfo-Move-launched-applications-into-tran.patch create mode 100644 0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch create mode 100644 0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch 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 +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 +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 +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 +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 - 2.67.3-2 +- Add patches to move applications into systemd scopes + * Thu Feb 04 2021 Kalev Lember - 2.67.3-1 - Update to 2.67.3 - Fix gtk-doc directory ownership