[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / gsubprocess.c
index cafbcbb..999d777 100644 (file)
@@ -18,6 +18,7 @@
  * SECTION:gsubprocess
  * @title: GSubprocess
  * @short_description: Child processes
+ * @include: gio/gio.h
  * @see_also: #GSubprocessLauncher
  *
  * #GSubprocess allows the creation of and interaction with child
  * comprehensive API for asynchronous I/O, such
  * g_output_stream_splice_async().  This makes GSubprocess
  * significantly more powerful and flexible than equivalent APIs in
- * some other languages such as the <literal>subprocess.py</literal>
+ * some other languages such as the `subprocess.py`
  * included with Python.  For example, using #GSubprocess one could
  * create two child processes, reading standard output from the first,
  * processing it, and writing to the input stream of the second, all
  * without blocking the main loop.
  *
  * A powerful g_subprocess_communicate() API is provided similar to the
- * <literal>communicate()</literal> method of
- * <literal>subprocess.py</literal>.  This enables very easy interaction
- * with a subprocess that has been opened with pipes.
+ * `communicate()` method of `subprocess.py`. This enables very easy
+ * interaction with a subprocess that has been opened with pipes.
  *
  * #GSubprocess defaults to tight control over the file descriptors open
  * in the child process, avoiding dangling-fd issues that are caused by
@@ -71,8 +71,8 @@
  * change of working directory, child setup functions, etc).
  *
  * A typical use of #GSubprocess will involve calling
- * g_subprocess_new(), followed by g_subprocess_wait() or
- * g_subprocess_wait_sync().  After the process exits, the status can be
+ * g_subprocess_new(), followed by g_subprocess_wait_async() or
+ * g_subprocess_wait().  After the process exits, the status can be
  * checked using functions such as g_subprocess_get_if_exited() (which
  * are similar to the familiar WIFEXITED-style POSIX macros).
  *
 #define O_BINARY 0
 #endif
 
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#else
+#define HAVE_O_CLOEXEC 1
+#endif
+
 #define COMMUNICATE_READ_SIZE 4096
 
 /* A GSubprocess can have two possible states: running and not.
@@ -356,6 +362,10 @@ unix_open_file (const char  *filename,
       g_free (display_name);
       /* fall through... */
     }
+#ifndef HAVE_O_CLOEXEC
+  else
+    fcntl (my_fd, F_SETFD, FD_CLOEXEC);
+#endif
 
   return my_fd;
 }
@@ -405,6 +415,7 @@ g_subprocess_exited (GPid     pid,
   while (tasks)
     {
       g_task_return_boolean (tasks->data, TRUE);
+      g_object_unref (tasks->data);
       tasks = g_slist_delete_link (tasks, tasks);
     }
 
@@ -597,7 +608,9 @@ g_subprocess_finalize (GObject *object)
   g_clear_object (&self->stdin_pipe);
   g_clear_object (&self->stdout_pipe);
   g_clear_object (&self->stderr_pipe);
-  g_free (self->argv);
+  g_strfreev (self->argv);
+
+  g_mutex_clear (&self->pending_waits_lock);
 
   G_OBJECT_CLASS (g_subprocess_parent_class)->finalize (object);
 }
@@ -605,6 +618,7 @@ g_subprocess_finalize (GObject *object)
 static void
 g_subprocess_init (GSubprocess  *self)
 {
+  g_mutex_init (&self->pending_waits_lock);
 }
 
 static void
@@ -635,8 +649,8 @@ g_subprocess_class_init (GSubprocessClass *class)
  * g_subprocess_new: (skip)
  * @flags: flags that define the behaviour of the subprocess
  * @error: (allow-none): return location for an error, or %NULL
- * @argv0: first commandline argument to pass to the subprocess,
- *     followed by more arguments, followed by %NULL
+ * @argv0: first commandline argument to pass to the subprocess
+ * @...:   more commandline arguments, followed by %NULL
  *
  * Create a new process with the given flags and varargs argument
  * list.  By default, matching the g_spawn_async() defaults, the
@@ -672,6 +686,7 @@ g_subprocess_new (GSubprocessFlags   flags,
   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_newv ((const gchar * const *) args->pdata, flags, error);
 
@@ -682,7 +697,7 @@ g_subprocess_new (GSubprocessFlags   flags,
 
 /**
  * g_subprocess_newv:
- * @argv: commandline arguments for the subprocess
+ * @argv: (array zero-terminated=1) (element-type utf8): commandline arguments for the subprocess
  * @flags: flags that define the behaviour of the subprocess
  * @error: (allow-none): return location for an error, or %NULL
  *
@@ -709,6 +724,13 @@ g_subprocess_newv (const gchar * const  *argv,
                          NULL);
 }
 
+/**
+ * g_subprocess_get_identifier:
+ * @subprocess: a #GSubprocess
+ *
+ * On UNIX, returns the process ID as a decimal string.
+ * On Windows, returns the result of GetProcessId() also as a string.
+ */
 const gchar *
 g_subprocess_get_identifier (GSubprocess *subprocess)
 {
@@ -730,7 +752,7 @@ g_subprocess_get_identifier (GSubprocess *subprocess)
  * The process must have been created with
  * %G_SUBPROCESS_FLAGS_STDIN_PIPE.
  *
- * Returns: the stdout pipe
+ * Returns: (transfer none): the stdout pipe
  *
  * Since: 2.40
  **/
@@ -753,7 +775,7 @@ g_subprocess_get_stdin_pipe (GSubprocess *subprocess)
  * The process must have been created with
  * %G_SUBPROCESS_FLAGS_STDOUT_PIPE.
  *
- * Returns: the stdout pipe
+ * Returns: (transfer none): the stdout pipe
  *
  * Since: 2.40
  **/
@@ -776,7 +798,7 @@ g_subprocess_get_stdout_pipe (GSubprocess *subprocess)
  * The process must have been created with
  * %G_SUBPROCESS_FLAGS_STDERR_PIPE.
  *
- * Returns: the stderr pipe
+ * Returns: (transfer none): the stderr pipe
  *
  * Since: 2.40
  **/
@@ -919,6 +941,9 @@ g_subprocess_sync_complete (GAsyncResult **result)
  * This function does not fail in the case of the subprocess having
  * abnormal termination.  See g_subprocess_wait_check() for that.
  *
+ * Cancelling @cancellable doesn't kill the subprocess.  Call
+ * g_subprocess_force_exit() if it is desirable.
+ *
  * Returns: %TRUE on success, %FALSE if @cancellable was cancelled
  *
  * Since: 2.40
@@ -1399,7 +1424,7 @@ g_subprocess_communicate_made_progress (GObject      *source_object,
       source == state->stdout_buf ||
       source == state->stderr_buf)
     {
-      if (!g_output_stream_splice_finish ((GOutputStream*)source, result, &error))
+      if (g_output_stream_splice_finish ((GOutputStream*) source, result, &error) == -1)
         goto out;
 
       if (source == state->stdout_buf ||
@@ -1467,13 +1492,17 @@ g_subprocess_communicate_state_free (gpointer data)
 {
   CommunicateState *state = data;
 
+  g_clear_object (&state->cancellable);
   g_clear_object (&state->stdin_buf);
   g_clear_object (&state->stdout_buf);
   g_clear_object (&state->stderr_buf);
 
-  if (!g_source_is_destroyed (state->cancellable_source))
-    g_source_destroy (state->cancellable_source);
-  g_source_unref (state->cancellable_source);
+  if (state->cancellable_source)
+    {
+      if (!g_source_is_destroyed (state->cancellable_source))
+        g_source_destroy (state->cancellable_source);
+      g_source_unref (state->cancellable_source);
+    }
 
   g_slice_free (CommunicateState, state);
 }
@@ -1539,13 +1568,14 @@ g_subprocess_communicate_internal (GSubprocess         *subprocess,
                            g_subprocess_communicate_made_progress, g_object_ref (task));
   state->outstanding_ops++;
 
+  g_object_unref (task);
   return state;
 }
 
 /**
  * g_subprocess_communicate:
  * @subprocess: a #GSubprocess
- * @stdin_buf: data to send to the stdin of the subprocess, or %NULL
+ * @stdin_buf: (allow-none): data to send to the stdin of the subprocess, or %NULL
  * @cancellable: a #GCancellable
  * @stdout_buf: (out): data read from the subprocess stdout
  * @stderr_buf: (out): data read from the subprocess stderr
@@ -1554,7 +1584,7 @@ g_subprocess_communicate_internal (GSubprocess         *subprocess,
  * Communicate with the subprocess until it terminates, and all input
  * and output has been completed.
  *
- * If @stdin is given, the subprocess must have been created with
+ * If @stdin_buf is given, the subprocess must have been created with
  * %G_SUBPROCESS_FLAGS_STDIN_PIPE.  The given data is fed to the
  * stdin of the subprocess and the pipe is closed (ie: EOF).
  *
@@ -1626,8 +1656,8 @@ g_subprocess_communicate (GSubprocess   *subprocess,
 /**
  * g_subprocess_communicate_async:
  * @subprocess: Self
- * @stdin_buf: Input data
- * @cancellable: Cancellable
+ * @stdin_buf: (allow-none): Input data, or %NULL
+ * @cancellable: (allow-none): Cancellable
  * @callback: Callback
  * @user_data: User data
  *
@@ -1692,7 +1722,7 @@ g_subprocess_communicate_finish (GSubprocess   *subprocess,
 /**
  * g_subprocess_communicate_utf8:
  * @subprocess: a #GSubprocess
- * @stdin_buf: data to send to the stdin of the subprocess, or %NULL
+ * @stdin_buf: (allow-none): data to send to the stdin of the subprocess, or %NULL
  * @cancellable: a #GCancellable
  * @stdout_buf: (out): data read from the subprocess stdout
  * @stderr_buf: (out): data read from the subprocess stderr
@@ -1712,13 +1742,16 @@ g_subprocess_communicate_utf8 (GSubprocess   *subprocess,
   GAsyncResult *result = NULL;
   gboolean success;
   GBytes *stdin_bytes;
+  size_t stdin_buf_len = 0;
 
   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
   g_return_val_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE), FALSE);
   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  stdin_bytes = g_bytes_new (stdin_buf, strlen (stdin_buf));
+  if (stdin_buf != NULL)
+    stdin_buf_len = strlen (stdin_buf);
+  stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len);
 
   g_subprocess_sync_setup ();
   g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable,
@@ -1734,12 +1767,12 @@ g_subprocess_communicate_utf8 (GSubprocess   *subprocess,
 /**
  * g_subprocess_communicate_utf8_async:
  * @subprocess: Self
- * @stdin_buf: Input data
+ * @stdin_buf: (allow-none): Input data, or %NULL
  * @cancellable: Cancellable
  * @callback: Callback
  * @user_data: User data
  *
- * Asynchronous version of g_subprocess_communicate_utf().  Complete
+ * Asynchronous version of g_subprocess_communicate_utf8().  Complete
  * invocation with g_subprocess_communicate_utf8_finish().
  */
 void
@@ -1750,13 +1783,18 @@ g_subprocess_communicate_utf8_async (GSubprocess         *subprocess,
                                      gpointer             user_data)
 {
   GBytes *stdin_bytes;
+  size_t stdin_buf_len = 0;
 
   g_return_if_fail (G_IS_SUBPROCESS (subprocess));
   g_return_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE));
   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
-  stdin_bytes = g_bytes_new (stdin_buf, strlen (stdin_buf));
+  if (stdin_buf != NULL)
+    stdin_buf_len = strlen (stdin_buf);
+  stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len);
+
   g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable, callback, user_data);
+
   g_bytes_unref (stdin_bytes);
 }