GApplication: Plug a memory leak
[platform/upstream/glib.git] / gio / gsubprocesslauncher.c
index e8e2ad2..fbcbf6a 100644 (file)
  */
 
 /**
- * SECTION:gsubprocess
+ * SECTION:gsubprocesslauncher
  * @title: GSubprocess Launcher
  * @short_description: Environment options for launching a child process
+ * @include: gio/gio.h
  *
  * This class contains a set of options for launching child processes,
  * such as where its standard input and output will be directed, the
@@ -131,10 +132,9 @@ g_subprocess_launcher_finalize (GObject *object)
 {
   GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
 
-  g_strfreev (self->envp);
-  g_free (self->cwd);
-
 #ifdef G_OS_UNIX
+  guint i;
+
   g_free (self->stdin_path);
   g_free (self->stdout_path);
   g_free (self->stderr_path);
@@ -148,12 +148,25 @@ g_subprocess_launcher_finalize (GObject *object)
   if (self->stderr_fd != -1)
     close (self->stderr_fd);
 
-  g_clear_pointer (&self->basic_fd_assignments, g_array_unref);
-  g_clear_pointer (&self->needdup_fd_assignments, g_array_unref);
-#endif
+  if (self->basic_fd_assignments)
+    {
+      for (i = 0; i < self->basic_fd_assignments->len; i++)
+        (void) close (g_array_index (self->basic_fd_assignments, int, i));
+      g_array_unref (self->basic_fd_assignments);
+    }
+  if (self->needdup_fd_assignments)
+    {
+      for (i = 0; i < self->needdup_fd_assignments->len; i += 2)
+        (void) close (g_array_index (self->needdup_fd_assignments, int, i));
+      g_array_unref (self->needdup_fd_assignments);
+    }
 
   if (self->child_setup_destroy_notify)
     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
+#endif
+
+  g_strfreev (self->envp);
+  g_free (self->cwd);
 
   G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->finalize (object);
 }
@@ -161,12 +174,12 @@ g_subprocess_launcher_finalize (GObject *object)
 static void
 g_subprocess_launcher_init (GSubprocessLauncher  *self)
 {
-  self->envp = g_listenv ();
+  self->envp = g_get_environ ();
 
+#ifdef G_OS_UNIX
   self->stdin_fd = -1;
   self->stdout_fd = -1;
   self->stderr_fd = -1;
-#ifdef G_OS_UNIX
   self->basic_fd_assignments = g_array_new (FALSE, 0, sizeof (int));
   self->needdup_fd_assignments = g_array_new (FALSE, 0, sizeof (int));
 #endif
@@ -188,6 +201,7 @@ g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
 
 /**
  * g_subprocess_launcher_new:
+ * @flags: #GSubprocessFlags
  *
  * Creates a new #GSubprocessLauncher.
  *
@@ -211,7 +225,7 @@ g_subprocess_launcher_new (GSubprocessFlags flags)
 /**
  * g_subprocess_launcher_set_environ:
  * @self: a #GSubprocess
- * @environ: the replacement environment
+ * @env: the replacement environment
  *
  * Replace the entire environment of processes launched from this
  * launcher with the given 'environ' variable.
@@ -231,10 +245,10 @@ g_subprocess_launcher_new (GSubprocessFlags flags)
  **/
 void
 g_subprocess_launcher_set_environ (GSubprocessLauncher  *self,
-                                   gchar               **environ)
+                                   gchar               **env)
 {
   g_strfreev (self->envp);
-  self->envp = g_strdupv (environ);
+  self->envp = g_strdupv (env);
 }
 
 /**
@@ -264,7 +278,7 @@ g_subprocess_launcher_setenv (GSubprocessLauncher *self,
 }
 
 /**
- * g_subprocess_launcher_unsetsenv:
+ * g_subprocess_launcher_unsetenv:
  * @self: a #GSubprocess
  * @variable: the environment variable to unset, must not contain '='
  *
@@ -352,9 +366,21 @@ void
 g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
                                  GSubprocessFlags     flags)
 {
-  if (verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, self->stdin_fd, self->stdin_path) &&
-      verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, self->stdout_fd, self->stdout_path) &&
-      verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, self->stderr_fd, self->stderr_path))
+  const gchar *stdin_path = NULL, *stdout_path = NULL, *stderr_path = NULL;
+  gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
+
+#ifdef G_OS_UNIX
+  stdin_fd = self->stdin_fd;
+  stdout_fd = self->stdout_fd;
+  stderr_fd = self->stderr_fd;
+  stdin_path = self->stdin_path;
+  stdout_path = self->stdout_path;
+  stderr_path = self->stderr_path;
+#endif
+
+  if (verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, stdin_fd, stdin_path) &&
+      verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, stdout_fd, stdout_path) &&
+      verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, stderr_fd, stderr_path))
     self->flags = flags;
 }
 
@@ -570,23 +596,26 @@ g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
 }
 
 /**
- * g_subprocess_launcher_pass_fd:
+ * g_subprocess_launcher_take_fd:
  * @self: a #GSubprocessLauncher
  * @source_fd: File descriptor in parent process
  * @target_fd: Target descriptor for child process
  *
- * Pass an arbitrary file descriptor from parent process to
- * the child.  By default, all file descriptors from the parent
- * will be closed.  This function allows you to create (for example)
- * a custom pipe() or socketpair() before launching the process, and
- * choose the target descriptor in the child.
+ * Transfer an arbitrary file descriptor from parent process to the
+ * child.  This function takes "ownership" of the fd; it will be closed
+ * in the parent when @self is freed.
+ *
+ * By default, all file descriptors from the parent will be closed.
+ * This function allows you to create (for example) a custom pipe() or
+ * socketpair() before launching the process, and choose the target
+ * descriptor in the child.
  *
  * An example use case is GNUPG, which has a command line argument
  * --passphrase-fd providing a file descriptor number where it expects
  * the passphrase to be written.
  */
 void
-g_subprocess_launcher_pass_fd (GSubprocessLauncher   *self,
+g_subprocess_launcher_take_fd (GSubprocessLauncher   *self,
                                gint                   source_fd,
                                gint                   target_fd)
 {
@@ -646,8 +675,7 @@ g_subprocess_launcher_set_child_setup (GSubprocessLauncher  *self,
  * @argv0: Command line arguments
  * @...: Continued arguments, %NULL terminated
  *
- * A convenience helper for creating a #GSubprocess given a provided
- * varargs list of arguments.
+ * Creates a #GSubprocess given a provided varargs list of arguments.
  *
  * Since: 2.40
  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
@@ -673,6 +701,9 @@ g_subprocess_launcher_spawn (GSubprocessLauncher  *launcher,
   while ((arg = va_arg (ap, const gchar *)))
     g_ptr_array_add (args, (gchar *) arg);
 
+  g_ptr_array_add (args, NULL);
+  va_end (ap);
+
   result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
 
   g_ptr_array_free (args, TRUE);
@@ -684,11 +715,10 @@ g_subprocess_launcher_spawn (GSubprocessLauncher  *launcher,
 /**
  * g_subprocess_launcher_spawnv:
  * @self: a #GSubprocessLauncher
- * @argv: Command line arguments
+ * @argv: (array zero-terminated=1) (element-type utf8): Command line arguments
  * @error: Error
  *
- * A convenience helper for creating a #GSubprocess given a provided
- * array of arguments.
+ * Creates a #GSubprocess given a provided array of arguments.
  *
  * Since: 2.40
  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)