[glib: 1/10] Revert "gdesktopappinfo: Use `sh` rather than `gio-launch-desktop`"




commit d0967c1d4acd944a2c71467b258a1b5afc37790e
Author: Simon McVittie <smcv collabora com>
Date:   Thu Jul 14 12:02:51 2022 +0100

    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>

 gio/gdesktopappinfo.c    | 46 ++++++++++++++++++------------------------
 gio/gio-launch-desktop.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 gio/meson.build          |  6 ++++++
 gio/tests/meson.build    |  1 +
 4 files changed, 78 insertions(+), 27 deletions(-)
---
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index c0950ae759..20cf2af8cc 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 0000000000..03845df28d
--- /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 e641354193..b520b5a7bf 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 282b911c72..c3e5489329 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


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