[glib] gsubprocess: Copy parent process’ environ when clearing subprocess’



commit e1e73dafa6eeae3e045bf054e132c2c70ff2bcc0
Author: Philip Withnall <withnall endlessm com>
Date:   Thu Mar 30 11:02:14 2017 +0100

    gsubprocess: Copy parent process’ environ when clearing subprocess’
    
    Previously, this was done at the time of spawning the subprocess, which
    meant the g_subprocess_launcher_*_environ() functions could not be used
    to modify the parent process’ environment.
    
    Change the code to copy the parent process’ environment when
    g_subprocess_launcher_set_environ(NULL) is called. Document the change
    and add a unit test.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=778422

 gio/gsubprocesslauncher.c |   11 ++++++++-
 gio/tests/gsubprocess.c   |   46 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)
---
diff --git a/gio/gsubprocesslauncher.c b/gio/gsubprocesslauncher.c
index 6a7e265..5cdec4d 100644
--- a/gio/gsubprocesslauncher.c
+++ b/gio/gsubprocesslauncher.c
@@ -240,8 +240,12 @@ g_subprocess_launcher_new (GSubprocessFlags flags)
  * As an alternative, you can use g_subprocess_launcher_setenv(),
  * g_subprocess_launcher_unsetenv(), etc.
  *
- * Pass %NULL to inherit the parent  process' environment. Pass an
- * empty array to set an empty environment.
+ * Pass an empty array to set an empty environment. Pass %NULL to inherit the
+ * parent process’ environment. As of GLib 2.54, the parent process’ environment
+ * will be copied when g_subprocess_launcher_set_environ() is called.
+ * Previously, it was copied when the subprocess was executed. This means the
+ * copied environment may now be modified (using g_subprocess_launcher_setenv(),
+ * etc.) before launching the subprocess.
  *
  * On UNIX, all strings in this array can be arbitrary byte strings.
  * On Windows, they should be in UTF-8.
@@ -254,6 +258,9 @@ g_subprocess_launcher_set_environ (GSubprocessLauncher  *self,
 {
   g_strfreev (self->envp);
   self->envp = g_strdupv (env);
+
+  if (self->envp == NULL)
+    self->envp = g_get_environ ();
 }
 
 /**
diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c
index e1270b1..7200226 100644
--- a/gio/tests/gsubprocess.c
+++ b/gio/tests/gsubprocess.c
@@ -948,6 +948,51 @@ test_env (void)
   g_object_unref (proc);
 }
 
+/* Test that explicitly inheriting and modifying the parent process’
+ * environment works. */
+static void
+test_env_inherit (void)
+{
+  GError *local_error = NULL;
+  GError **error = &local_error;
+  GSubprocessLauncher *launcher;
+  GSubprocess *proc;
+  GPtrArray *args;
+  GInputStream *stdout;
+  gchar *result;
+  gchar **split;
+
+  g_setenv ("TEST_ENV_INHERIT1", "1", TRUE);
+  g_setenv ("TEST_ENV_INHERIT2", "2", TRUE);
+
+  args = get_test_subprocess_args ("env", NULL);
+  launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
+  g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
+  g_subprocess_launcher_set_environ (launcher, NULL);
+  g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
+  g_subprocess_launcher_unsetenv (launcher, "TEST_ENV_INHERIT1");
+
+  g_assert_null (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT1"));
+  g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT2"), ==, "2");
+  g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TWO"), ==, "2");
+
+  proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
+  g_ptr_array_free (args, TRUE);
+  g_assert_no_error (local_error);
+
+  stdout = g_subprocess_get_stdout_pipe (proc);
+
+  result = splice_to_string (stdout, error);
+  split = g_strsplit (result, "\n", -1);
+  g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1"));
+  g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2");
+  g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
+
+  g_strfreev (split);
+  g_free (result);
+  g_object_unref (proc);
+}
+
 static void
 test_cwd (void)
 {
@@ -1265,6 +1310,7 @@ main (int argc, char **argv)
   g_test_add_func ("/gsubprocess/communicate-nothing", test_communicate_nothing);
   g_test_add_func ("/gsubprocess/terminate", test_terminate);
   g_test_add_func ("/gsubprocess/env", test_env);
+  g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit);
   g_test_add_func ("/gsubprocess/cwd", test_cwd);
 #ifdef G_OS_UNIX
   g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);


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