diff options
author | Simon McVittie <smcv@collabora.com> | 2022-07-14 12:02:51 +0100 |
---|---|---|
committer | Philip Withnall <pwithnall@endlessos.org> | 2022-07-25 01:00:53 +0200 |
commit | d0967c1d4acd944a2c71467b258a1b5afc37790e (patch) | |
tree | 2189ed763938efdfa46fcded24f88151f30f2ebd | |
parent | 206be0a8a190c5aa78ed650b9091983ad796aec2 (diff) | |
download | glib-d0967c1d4acd944a2c71467b258a1b5afc37790e.tar.gz |
Revert "gdesktopappinfo: Use `sh` rather than `gio-launch-desktop`"
A shell one-liner was enough to set GIO_LAUNCHED_DESKTOP_FILE_PID,
but ideally we also want to do the equivalent of sd_journal_stream_fd()
to set up its standard output and standard error streams.
Ideally we would call sd_journal_stream_fd() in a process that will
exec the real program, otherwise it will report the wrong process ID
in the Journal, but we can't easily do that in a forked child when
using posix_spawn() for subprocesses.
This reverts commit 2b533ca99ad07090d7090ad7389d1e85230aa618.
Signed-off-by: Simon McVittie <smcv@collabora.com>
-rw-r--r-- | gio/gdesktopappinfo.c | 46 | ||||
-rw-r--r-- | gio/gio-launch-desktop.c | 52 | ||||
-rw-r--r-- | gio/meson.build | 6 | ||||
-rw-r--r-- | gio/tests/meson.build | 1 |
4 files changed, 78 insertions, 27 deletions
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index c0950ae75..20cf2af8c 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -165,6 +165,7 @@ static const gchar *desktop_file_dirs_config_dir = NULL; static DesktopFileDir *desktop_file_dir_user_config = NULL; /* (owned) */ static DesktopFileDir *desktop_file_dir_user_data = NULL; /* (owned) */ static GMutex desktop_file_dir_lock; +static const gchar *gio_launch_desktop_path = NULL; /* Monitor 'changed' signal handler {{{2 */ static void desktop_file_dir_reset (DesktopFileDir *dir); @@ -2872,15 +2873,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, 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 */ - }; old_uris = dup_uris; if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error)) @@ -2924,26 +2916,26 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, emit_launch_started (launch_context, info, sn_id); } - /* Wrap the @argv in a command which will set the - * `GIO_LAUNCHED_DESKTOP_FILE_PID` environment variable. We can’t set this - * in @envp along with `GIO_LAUNCHED_DESKTOP_FILE` because we need to know - * the PID of the new forked process. We can’t use setenv() between fork() - * and exec() because we’d rather use posix_spawn() for speed. - * - * `sh` should be available on all the platforms that `GDesktopAppInfo` - * currently supports (since they are all POSIX). If additional platforms - * need to be supported in future, it will probably have to be replaced - * 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); - - for (j = 0; j < G_N_ELEMENTS (wrapper_argv); j++) - wrapped_argv[j] = g_strdup (wrapper_argv[j]); + if (g_once_init_enter (&gio_launch_desktop_path)) + { + const gchar *tmp; + + /* Allow test suite to specify path to gio-launch-desktop */ + tmp = g_getenv ("GIO_LAUNCH_DESKTOP"); + + /* Fall back on usual searching in $PATH */ + if (tmp == NULL) + tmp = "gio-launch-desktop"; + g_once_init_leave (&gio_launch_desktop_path, tmp); + } + + wrapped_argv = g_new (char *, argc + 2); + wrapped_argv[0] = g_strdup (gio_launch_desktop_path); + for (i = 0; i < argc; i++) - wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = g_steal_pointer (&argv[i]); + wrapped_argv[i + 1] = g_steal_pointer (&argv[i]); - wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = NULL; + wrapped_argv[i + 1] = NULL; g_free (argv); argv = NULL; diff --git a/gio/gio-launch-desktop.c b/gio/gio-launch-desktop.c new file mode 100644 index 000000000..03845df28 --- /dev/null +++ b/gio/gio-launch-desktop.c @@ -0,0 +1,52 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2018 Endless Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * Author: Daniel Drake <drake@endlessm.com> + */ + +/* + * gio-launch-desktop: GDesktopAppInfo helper + * Executable wrapper to set GIO_LAUNCHED_DESKTOP_FILE_PID + * There are complications when doing this in a fork()/exec() codepath, + * and it cannot otherwise be done with posix_spawn(). + * This wrapper is designed to be minimal and lightweight. + * It does not even link against glib. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +int +main (int argc, char *argv[]) +{ + pid_t pid = getpid (); + char buf[50]; + int r; + + if (argc < 2) + return -1; + + r = snprintf (buf, sizeof (buf), "GIO_LAUNCHED_DESKTOP_FILE_PID=%ld", (long) pid); + if (r >= sizeof (buf)) + return -1; + + putenv (buf); + + return execvp (argv[1], argv + 1); +} diff --git a/gio/meson.build b/gio/meson.build index e64135419..b520b5a7b 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -399,6 +399,12 @@ if host_system != 'windows' contenttype_sources += files('gcontenttype.c') appinfo_sources += files('gdesktopappinfo.c') gio_unix_include_headers += files('gdesktopappinfo.h') + + executable('gio-launch-desktop', 'gio-launch-desktop.c', + install : true, + c_args : gio_c_args, + # intl.lib is not compatible with SAFESEH + link_args : noseh_link_args) endif subdir('xdgmime') diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 282b911c7..c3e548932 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -148,6 +148,7 @@ test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) test_env.set('GIO_MODULE_DIR', '') +test_env.set('GIO_LAUNCH_DESKTOP', meson.build_root() + '/gio/gio-launch-desktop') # Check for libdbus1 - Optional - is only used in the GDBus test cases # 1.2.14 required for dbus_message_set_serial |