LCOV - code coverage report
Current view: top level - glib/gio - gsubprocess.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 441 469 94.0 %
Date: 2024-04-23 05:16:05 Functions: 51 52 98.1 %
Branches: 167 203 82.3 %

           Branch data     Line data    Source code
       1                 :            : /* GIO - GLib Input, Output and Streaming Library
       2                 :            :  *
       3                 :            :  * Copyright © 2012, 2013 Red Hat, Inc.
       4                 :            :  * Copyright © 2012, 2013 Canonical Limited
       5                 :            :  *
       6                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       7                 :            :  *
       8                 :            :  * This library is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Lesser General Public
      10                 :            :  * License as published by the Free Software Foundation; either
      11                 :            :  * version 2.1 of the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * See the included COPYING file for more information.
      14                 :            :  *
      15                 :            :  * Authors: Colin Walters <walters@verbum.org>
      16                 :            :  *          Ryan Lortie <desrt@desrt.ca>
      17                 :            :  */
      18                 :            : 
      19                 :            : /**
      20                 :            :  * GSubprocess:
      21                 :            :  *
      22                 :            :  * `GSubprocess` allows the creation of and interaction with child
      23                 :            :  * processes.
      24                 :            :  *
      25                 :            :  * Processes can be communicated with using standard GIO-style APIs (ie:
      26                 :            :  * [class@Gio.InputStream], [class@Gio.OutputStream]). There are GIO-style APIs
      27                 :            :  * to wait for process termination (ie: cancellable and with an asynchronous
      28                 :            :  * variant).
      29                 :            :  *
      30                 :            :  * There is an API to force a process to terminate, as well as a
      31                 :            :  * race-free API for sending UNIX signals to a subprocess.
      32                 :            :  *
      33                 :            :  * One major advantage that GIO brings over the core GLib library is
      34                 :            :  * comprehensive API for asynchronous I/O, such
      35                 :            :  * [method@Gio.OutputStream.splice_async].  This makes `GSubprocess`
      36                 :            :  * significantly more powerful and flexible than equivalent APIs in
      37                 :            :  * some other languages such as the `subprocess.py`
      38                 :            :  * included with Python.  For example, using `GSubprocess` one could
      39                 :            :  * create two child processes, reading standard output from the first,
      40                 :            :  * processing it, and writing to the input stream of the second, all
      41                 :            :  * without blocking the main loop.
      42                 :            :  *
      43                 :            :  * A powerful [method@Gio.Subprocess.communicate] API is provided similar to the
      44                 :            :  * `communicate()` method of `subprocess.py`. This enables very easy
      45                 :            :  * interaction with a subprocess that has been opened with pipes.
      46                 :            :  *
      47                 :            :  * `GSubprocess` defaults to tight control over the file descriptors open
      48                 :            :  * in the child process, avoiding dangling-FD issues that are caused by
      49                 :            :  * a simple `fork()`/`exec()`.  The only open file descriptors in the
      50                 :            :  * spawned process are ones that were explicitly specified by the
      51                 :            :  * `GSubprocess` API (unless `G_SUBPROCESS_FLAGS_INHERIT_FDS` was
      52                 :            :  * specified).
      53                 :            :  *
      54                 :            :  * `GSubprocess` will quickly reap all child processes as they exit,
      55                 :            :  * avoiding ‘zombie processes’ remaining around for long periods of
      56                 :            :  * time.  [method@Gio.Subprocess.wait] can be used to wait for this to happen,
      57                 :            :  * but it will happen even without the call being explicitly made.
      58                 :            :  *
      59                 :            :  * As a matter of principle, `GSubprocess` has no API that accepts
      60                 :            :  * shell-style space-separated strings.  It will, however, match the
      61                 :            :  * typical shell behaviour of searching the `PATH` for executables that do
      62                 :            :  * not contain a directory separator in their name. By default, the `PATH`
      63                 :            :  * of the current process is used.  You can specify
      64                 :            :  * `G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP` to use the `PATH` of the
      65                 :            :  * launcher environment instead.
      66                 :            :  *
      67                 :            :  * `GSubprocess` attempts to have a very simple API for most uses (ie:
      68                 :            :  * spawning a subprocess with arguments and support for most typical
      69                 :            :  * kinds of input and output redirection).  See [ctor@Gio.Subprocess.new]. The
      70                 :            :  * [class@Gio.SubprocessLauncher] API is provided for more complicated cases
      71                 :            :  * (advanced types of redirection, environment variable manipulation,
      72                 :            :  * change of working directory, child setup functions, etc).
      73                 :            :  *
      74                 :            :  * A typical use of `GSubprocess` will involve calling
      75                 :            :  * [ctor@Gio.Subprocess.new], followed by [method@Gio.Subprocess.wait_async] or
      76                 :            :  * [method@Gio.Subprocess.wait].  After the process exits, the status can be
      77                 :            :  * checked using functions such as [method@Gio.Subprocess.get_if_exited] (which
      78                 :            :  * are similar to the familiar `WIFEXITED`-style POSIX macros).
      79                 :            :  *
      80                 :            :  * Note that as of GLib 2.82, creating a `GSubprocess` causes the signal
      81                 :            :  * `SIGPIPE` to be ignored for the remainder of the program. If you are writing
      82                 :            :  * a command-line utility that uses `GSubprocess`, you may need to take into
      83                 :            :  * account the fact that your program will not automatically be killed
      84                 :            :  * if it tries to write to `stdout` after it has been closed.
      85                 :            :  *
      86                 :            :  * Since: 2.40
      87                 :            :  **/
      88                 :            : 
      89                 :            : #include "config.h"
      90                 :            : 
      91                 :            : #include "gsubprocess.h"
      92                 :            : #include "gsubprocesslauncher-private.h"
      93                 :            : #include "gasyncresult.h"
      94                 :            : #include "giostream.h"
      95                 :            : #include "gmemoryinputstream.h"
      96                 :            : #include "glibintl.h"
      97                 :            : #include "glib-private.h"
      98                 :            : 
      99                 :            : #include <string.h>
     100                 :            : #ifdef G_OS_UNIX
     101                 :            : #include <gio/gunixoutputstream.h>
     102                 :            : #include <gio/gfiledescriptorbased.h>
     103                 :            : #include <gio/gunixinputstream.h>
     104                 :            : #include <gstdio.h>
     105                 :            : #include <glib-unix.h>
     106                 :            : #include <fcntl.h>
     107                 :            : #endif
     108                 :            : #ifdef G_OS_WIN32
     109                 :            : #include <windows.h>
     110                 :            : #include <io.h>
     111                 :            : #include "giowin32-priv.h"
     112                 :            : #endif
     113                 :            : 
     114                 :            : #ifndef O_BINARY
     115                 :            : #define O_BINARY 0
     116                 :            : #endif
     117                 :            : 
     118                 :            : #ifndef O_CLOEXEC
     119                 :            : #define O_CLOEXEC 0
     120                 :            : #else
     121                 :            : #define HAVE_O_CLOEXEC 1
     122                 :            : #endif
     123                 :            : 
     124                 :            : #define COMMUNICATE_READ_SIZE 4096
     125                 :            : 
     126                 :            : /* A GSubprocess can have two possible states: running and not.
     127                 :            :  *
     128                 :            :  * These two states are reflected by the value of 'pid'.  If it is
     129                 :            :  * non-zero then the process is running, with that pid.
     130                 :            :  *
     131                 :            :  * When a GSubprocess is first created with g_object_new() it is not
     132                 :            :  * running.  When it is finalized, it is also not running.
     133                 :            :  *
     134                 :            :  * During initable_init(), if the g_spawn() is successful then we
     135                 :            :  * immediately register a child watch and take an extra ref on the
     136                 :            :  * subprocess.  That reference doesn't drop until the child has quit,
     137                 :            :  * which is why finalize can only happen in the non-running state.  In
     138                 :            :  * the event that the g_spawn() failed we will still be finalizing a
     139                 :            :  * non-running GSubprocess (before returning from g_subprocess_new())
     140                 :            :  * with NULL.
     141                 :            :  *
     142                 :            :  * We make extensive use of the glib worker thread to guarantee
     143                 :            :  * race-free operation.  As with all child watches, glib calls waitpid()
     144                 :            :  * in the worker thread.  It reports the child exiting to us via the
     145                 :            :  * worker thread (which means that we can do synchronous waits without
     146                 :            :  * running a separate loop).  We also send signals to the child process
     147                 :            :  * via the worker thread so that we don't race with waitpid() and
     148                 :            :  * accidentally send a signal to an already-reaped child.
     149                 :            :  */
     150                 :            : static void initable_iface_init (GInitableIface         *initable_iface);
     151                 :            : 
     152                 :            : typedef GObjectClass GSubprocessClass;
     153                 :            : 
     154                 :            : struct _GSubprocess
     155                 :            : {
     156                 :            :   GObject parent;
     157                 :            : 
     158                 :            :   /* only used during construction */
     159                 :            :   GSubprocessLauncher *launcher;
     160                 :            :   GSubprocessFlags flags;
     161                 :            :   gchar **argv;
     162                 :            : 
     163                 :            :   /* state tracking variables */
     164                 :            :   gchar identifier[24];
     165                 :            :   int status;
     166                 :            :   GPid pid;
     167                 :            : 
     168                 :            :   /* list of GTask */
     169                 :            :   GMutex pending_waits_lock;
     170                 :            :   GSList *pending_waits;
     171                 :            : 
     172                 :            :   /* These are the streams created if a pipe is requested via flags. */
     173                 :            :   GOutputStream *stdin_pipe;
     174                 :            :   GInputStream  *stdout_pipe;
     175                 :            :   GInputStream  *stderr_pipe;
     176                 :            : };
     177                 :            : 
     178   [ +  +  +  -  :        619 : G_DEFINE_TYPE_WITH_CODE (GSubprocess, g_subprocess, G_TYPE_OBJECT,
                   +  + ]
     179                 :            :                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
     180                 :            : 
     181                 :            : enum
     182                 :            : {
     183                 :            :   PROP_0,
     184                 :            :   PROP_FLAGS,
     185                 :            :   PROP_ARGV,
     186                 :            :   N_PROPS
     187                 :            : };
     188                 :            : 
     189                 :            : static GInputStream *
     190                 :        174 : platform_input_stream_from_spawn_fd (gint fd)
     191                 :            : {
     192         [ +  + ]:        174 :   if (fd < 0)
     193                 :        120 :     return NULL;
     194                 :            : 
     195                 :            : #ifdef G_OS_UNIX
     196                 :         54 :   return g_unix_input_stream_new (fd, TRUE);
     197                 :            : #else
     198                 :            :   return g_win32_input_stream_new_from_fd (fd, TRUE);
     199                 :            : #endif
     200                 :            : }
     201                 :            : 
     202                 :            : static GOutputStream *
     203                 :         87 : platform_output_stream_from_spawn_fd (gint fd)
     204                 :            : {
     205         [ +  + ]:         87 :   if (fd < 0)
     206                 :         28 :     return NULL;
     207                 :            : 
     208                 :            : #ifdef G_OS_UNIX
     209                 :         59 :   return g_unix_output_stream_new (fd, TRUE);
     210                 :            : #else
     211                 :            :   return g_win32_output_stream_new_from_fd (fd, TRUE);
     212                 :            : #endif
     213                 :            : }
     214                 :            : 
     215                 :            : #ifdef G_OS_UNIX
     216                 :            : static gint
     217                 :          1 : unix_open_file (const char  *filename,
     218                 :            :                 gint         mode,
     219                 :            :                 GError     **error)
     220                 :            : {
     221                 :            :   gint my_fd;
     222                 :            : 
     223                 :          1 :   my_fd = g_open (filename, mode | O_BINARY | O_CLOEXEC, 0666);
     224                 :            : 
     225                 :            :   /* If we return -1 we should also set the error */
     226         [ -  + ]:          1 :   if (my_fd < 0)
     227                 :            :     {
     228                 :          0 :       gint saved_errno = errno;
     229                 :            :       char *display_name;
     230                 :            : 
     231                 :          0 :       display_name = g_filename_display_name (filename);
     232                 :          0 :       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno),
     233                 :            :                    _("Error opening file “%s”: %s"), display_name,
     234                 :            :                    g_strerror (saved_errno));
     235                 :          0 :       g_free (display_name);
     236                 :            :       /* fall through... */
     237                 :            :     }
     238                 :            : #ifndef HAVE_O_CLOEXEC
     239                 :            :   else
     240                 :            :     fcntl (my_fd, F_SETFD, FD_CLOEXEC);
     241                 :            : #endif
     242                 :            : 
     243                 :          1 :   return my_fd;
     244                 :            : }
     245                 :            : #endif
     246                 :            : 
     247                 :            : static void
     248                 :        176 : g_subprocess_set_property (GObject      *object,
     249                 :            :                            guint         prop_id,
     250                 :            :                            const GValue *value,
     251                 :            :                            GParamSpec   *pspec)
     252                 :            : {
     253                 :        176 :   GSubprocess *self = G_SUBPROCESS (object);
     254                 :            : 
     255      [ +  +  - ]:        176 :   switch (prop_id)
     256                 :            :     {
     257                 :         88 :     case PROP_FLAGS:
     258                 :         88 :       self->flags = g_value_get_flags (value);
     259                 :         88 :       break;
     260                 :            : 
     261                 :         88 :     case PROP_ARGV:
     262                 :         88 :       self->argv = g_value_dup_boxed (value);
     263                 :         88 :       break;
     264                 :            : 
     265                 :          0 :     default:
     266                 :            :       g_assert_not_reached ();
     267                 :            :     }
     268                 :        176 : }
     269                 :            : 
     270                 :            : static gboolean
     271                 :         87 : g_subprocess_exited (GPid     pid,
     272                 :            :                      gint     status,
     273                 :            :                      gpointer user_data)
     274                 :            : {
     275                 :         87 :   GSubprocess *self = user_data;
     276                 :            :   GSList *tasks;
     277                 :            : 
     278                 :         87 :   g_assert (self->pid == pid);
     279                 :            : 
     280                 :         87 :   g_mutex_lock (&self->pending_waits_lock);
     281                 :         87 :   self->status = status;
     282                 :         87 :   tasks = self->pending_waits;
     283                 :         87 :   self->pending_waits = NULL;
     284                 :         87 :   self->pid = 0;
     285                 :         87 :   g_mutex_unlock (&self->pending_waits_lock);
     286                 :            : 
     287                 :            :   /* Signal anyone in g_subprocess_wait_async() to wake up now */
     288         [ +  + ]:        140 :   while (tasks)
     289                 :            :     {
     290                 :         53 :       g_task_return_boolean (tasks->data, TRUE);
     291                 :         53 :       g_object_unref (tasks->data);
     292                 :         53 :       tasks = g_slist_delete_link (tasks, tasks);
     293                 :            :     }
     294                 :            : 
     295                 :         87 :   g_spawn_close_pid (pid);
     296                 :            : 
     297                 :         87 :   return FALSE;
     298                 :            : }
     299                 :            : 
     300                 :            : static gboolean
     301                 :         88 : initable_init (GInitable     *initable,
     302                 :            :                GCancellable  *cancellable,
     303                 :            :                GError       **error)
     304                 :            : {
     305                 :         88 :   GSubprocess *self = G_SUBPROCESS (initable);
     306                 :         88 :   gint *pipe_ptrs[3] = { NULL, NULL, NULL };
     307                 :         88 :   gint pipe_fds[3] = { -1, -1, -1 };
     308                 :         88 :   gint close_fds[3] = { -1, -1, -1 };
     309                 :            : #ifdef G_OS_UNIX
     310                 :         88 :   gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
     311                 :            : #endif
     312                 :         88 :   GSpawnFlags spawn_flags = 0;
     313                 :         88 :   gboolean success = FALSE;
     314                 :            :   gint i;
     315                 :            : 
     316                 :            :   /* this is a programmer error */
     317   [ +  +  +  -  :         88 :   if (!self->argv || !self->argv[0] || !self->argv[0][0])
                   -  + ]
     318                 :          1 :     return FALSE;
     319                 :            : 
     320         [ -  + ]:         87 :   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     321                 :          0 :     return FALSE;
     322                 :            : 
     323                 :            :   /* We must setup the three fds that will end up in the child as stdin,
     324                 :            :    * stdout and stderr.
     325                 :            :    *
     326                 :            :    * First, stdin.
     327                 :            :    */
     328         [ +  + ]:         87 :   if (self->flags & G_SUBPROCESS_FLAGS_STDIN_INHERIT)
     329                 :          1 :     spawn_flags |= G_SPAWN_CHILD_INHERITS_STDIN;
     330         [ +  + ]:         86 :   else if (self->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE)
     331                 :         59 :     pipe_ptrs[0] = &pipe_fds[0];
     332                 :            : #ifdef G_OS_UNIX
     333         [ +  + ]:         27 :   else if (self->launcher)
     334                 :            :     {
     335         [ -  + ]:         15 :       if (self->launcher->stdin_fd != -1)
     336                 :          0 :         stdin_fd = self->launcher->stdin_fd;
     337         [ -  + ]:         15 :       else if (self->launcher->stdin_path != NULL)
     338                 :            :         {
     339                 :          0 :           stdin_fd = close_fds[0] = unix_open_file (self->launcher->stdin_path, O_RDONLY, error);
     340         [ #  # ]:          0 :           if (stdin_fd == -1)
     341                 :          0 :             goto out;
     342                 :            :         }
     343                 :            :     }
     344                 :            : #endif
     345                 :            : 
     346                 :            :   /* Next, stdout. */
     347         [ +  + ]:         87 :   if (self->flags & G_SUBPROCESS_FLAGS_STDOUT_SILENCE)
     348                 :         10 :     spawn_flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
     349         [ +  + ]:         77 :   else if (self->flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
     350                 :         38 :     pipe_ptrs[1] = &pipe_fds[1];
     351                 :            : #ifdef G_OS_UNIX
     352         [ +  + ]:         39 :   else if (self->launcher)
     353                 :            :     {
     354         [ +  + ]:         14 :       if (self->launcher->stdout_fd != -1)
     355                 :          1 :         stdout_fd = self->launcher->stdout_fd;
     356         [ +  + ]:         13 :       else if (self->launcher->stdout_path != NULL)
     357                 :            :         {
     358                 :          1 :           stdout_fd = close_fds[1] = unix_open_file (self->launcher->stdout_path, O_CREAT | O_WRONLY, error);
     359         [ -  + ]:          1 :           if (stdout_fd == -1)
     360                 :          0 :             goto out;
     361                 :            :         }
     362                 :            :     }
     363                 :            : #endif
     364                 :            : 
     365                 :            :   /* Finally, stderr. */
     366         [ +  + ]:         87 :   if (self->flags & G_SUBPROCESS_FLAGS_STDERR_SILENCE)
     367                 :          1 :     spawn_flags |= G_SPAWN_STDERR_TO_DEV_NULL;
     368         [ +  + ]:         86 :   else if (self->flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
     369                 :         16 :     pipe_ptrs[2] = &pipe_fds[2];
     370                 :            : #ifdef G_OS_UNIX
     371         [ +  + ]:         70 :   else if (self->flags & G_SUBPROCESS_FLAGS_STDERR_MERGE)
     372                 :            :     /* This will work because stderr gets set up after stdout. */
     373                 :         10 :     stderr_fd = 1;
     374         [ +  + ]:         60 :   else if (self->launcher)
     375                 :            :     {
     376         [ -  + ]:         21 :       if (self->launcher->stderr_fd != -1)
     377                 :          0 :         stderr_fd = self->launcher->stderr_fd;
     378         [ -  + ]:         21 :       else if (self->launcher->stderr_path != NULL)
     379                 :            :         {
     380                 :          0 :           stderr_fd = close_fds[2] = unix_open_file (self->launcher->stderr_path, O_CREAT | O_WRONLY, error);
     381         [ #  # ]:          0 :           if (stderr_fd == -1)
     382                 :          0 :             goto out;
     383                 :            :         }
     384                 :            :     }
     385                 :            : #endif
     386                 :            : 
     387                 :            :   /* argv0 has no '/' in it?  We better do a PATH lookup. */
     388         [ +  + ]:         87 :   if (strchr (self->argv[0], G_DIR_SEPARATOR) == NULL)
     389                 :            :     {
     390   [ +  +  +  + ]:          4 :       if (self->launcher && self->launcher->flags & G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP)
     391                 :          1 :         spawn_flags |= G_SPAWN_SEARCH_PATH_FROM_ENVP;
     392                 :            :       else
     393                 :          3 :         spawn_flags |= G_SPAWN_SEARCH_PATH;
     394                 :            :     }
     395                 :            : 
     396         [ +  + ]:         87 :   if (self->flags & G_SUBPROCESS_FLAGS_INHERIT_FDS)
     397                 :          2 :     spawn_flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
     398                 :            : 
     399                 :         87 :   spawn_flags |= G_SPAWN_DO_NOT_REAP_CHILD;
     400                 :         87 :   spawn_flags |= G_SPAWN_CLOEXEC_PIPES;
     401                 :            : 
     402                 :        483 :   success = g_spawn_async_with_pipes_and_fds (self->launcher ? self->launcher->cwd : NULL,
     403         [ +  + ]:         87 :                                               (const gchar * const *) self->argv,
     404         [ +  + ]:         87 :                                               (const gchar * const *) (self->launcher ? self->launcher->envp : NULL),
     405                 :            :                                               spawn_flags,
     406                 :            : #ifdef G_OS_UNIX
     407         [ +  + ]:         87 :                                               self->launcher ? self->launcher->child_setup_func : NULL,
     408         [ +  + ]:         87 :                                               self->launcher ? self->launcher->child_setup_user_data : NULL,
     409                 :            :                                               stdin_fd, stdout_fd, stderr_fd,
     410         [ +  + ]:         87 :                                               self->launcher ? (const gint *) self->launcher->source_fds->data : NULL,
     411         [ +  + ]:         87 :                                               self->launcher ? (const gint *) self->launcher->target_fds->data : NULL,
     412         [ +  + ]:         87 :                                               self->launcher ? self->launcher->source_fds->len : 0,
     413                 :            : #else
     414                 :            :                                               NULL, NULL,
     415                 :            :                                               -1, -1, -1,
     416                 :            :                                               NULL, NULL, 0,
     417                 :            : #endif
     418                 :            :                                               &self->pid,
     419                 :            :                                               pipe_ptrs[0], pipe_ptrs[1], pipe_ptrs[2],
     420                 :            :                                               error);
     421                 :         87 :   g_assert (success == (self->pid != 0));
     422                 :            : 
     423                 :            :   {
     424                 :            :     guint64 identifier;
     425                 :            :     gint s G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
     426                 :            : 
     427                 :            : #ifdef G_OS_WIN32
     428                 :            :     identifier = (guint64) GetProcessId (self->pid);
     429                 :            : #else
     430                 :         87 :     identifier = (guint64) self->pid;
     431                 :            : #endif
     432                 :            : 
     433                 :         87 :     s = g_snprintf (self->identifier, sizeof self->identifier, "%"G_GUINT64_FORMAT, identifier);
     434                 :         87 :     g_assert (0 < s && (gsize) s < sizeof self->identifier);
     435                 :            :   }
     436                 :            : 
     437                 :            :   /* Start attempting to reap the child immediately */
     438         [ -  + ]:         87 :   if (success)
     439                 :            :     {
     440                 :            :       GMainContext *worker_context;
     441                 :            :       GSource *source;
     442                 :            : 
     443                 :         87 :       worker_context = GLIB_PRIVATE_CALL (g_get_worker_context) ();
     444                 :         87 :       source = g_child_watch_source_new (self->pid);
     445                 :         87 :       g_source_set_callback (source, (GSourceFunc) g_subprocess_exited, g_object_ref (self), g_object_unref);
     446                 :         87 :       g_source_attach (source, worker_context);
     447                 :         87 :       g_source_unref (source);
     448                 :            :     }
     449                 :            : 
     450                 :            : #ifdef G_OS_UNIX
     451                 :          0 : out:
     452                 :            : #endif
     453                 :            :   /* we don't need this past init... */
     454                 :         87 :   self->launcher = NULL;
     455                 :            : 
     456         [ +  + ]:        348 :   for (i = 0; i < 3; i++)
     457         [ +  + ]:        261 :     if (close_fds[i] != -1)
     458                 :          1 :       close (close_fds[i]);
     459                 :            : 
     460                 :         87 :   self->stdin_pipe = platform_output_stream_from_spawn_fd (pipe_fds[0]);
     461                 :         87 :   self->stdout_pipe = platform_input_stream_from_spawn_fd (pipe_fds[1]);
     462                 :         87 :   self->stderr_pipe = platform_input_stream_from_spawn_fd (pipe_fds[2]);
     463                 :            : 
     464                 :         87 :   return success;
     465                 :            : }
     466                 :            : 
     467                 :            : static void
     468                 :         76 : g_subprocess_finalize (GObject *object)
     469                 :            : {
     470                 :         76 :   GSubprocess *self = G_SUBPROCESS (object);
     471                 :            : 
     472                 :         76 :   g_assert (self->pending_waits == NULL);
     473                 :         76 :   g_assert (self->pid == 0);
     474                 :            : 
     475                 :         76 :   g_clear_object (&self->stdin_pipe);
     476                 :         76 :   g_clear_object (&self->stdout_pipe);
     477                 :         76 :   g_clear_object (&self->stderr_pipe);
     478                 :         76 :   g_strfreev (self->argv);
     479                 :            : 
     480                 :         76 :   g_mutex_clear (&self->pending_waits_lock);
     481                 :            : 
     482                 :         76 :   G_OBJECT_CLASS (g_subprocess_parent_class)->finalize (object);
     483                 :         76 : }
     484                 :            : 
     485                 :            : static void
     486                 :         88 : g_subprocess_init (GSubprocess  *self)
     487                 :            : {
     488                 :         88 :   g_mutex_init (&self->pending_waits_lock);
     489                 :         88 : }
     490                 :            : 
     491                 :            : static void
     492                 :         10 : initable_iface_init (GInitableIface *initable_iface)
     493                 :            : {
     494                 :         10 :   initable_iface->init = initable_init;
     495                 :         10 : }
     496                 :            : 
     497                 :            : static void
     498                 :         10 : g_subprocess_class_init (GSubprocessClass *class)
     499                 :            : {
     500                 :         10 :   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
     501                 :            : 
     502                 :            : #ifdef SIGPIPE
     503                 :            :   /* There is no portable, thread-safe way to avoid having the process
     504                 :            :    * be killed by SIGPIPE when calling write() on a pipe to a subprocess, so we
     505                 :            :    * are forced to simply ignore the signal process-wide.
     506                 :            :    *
     507                 :            :    * This can happen if `G_SUBPROCESS_FLAGS_STDIN_PIPE` is used and the
     508                 :            :    * subprocess calls close() on its stdin FD while the parent process is
     509                 :            :    * running g_subprocess_communicate().
     510                 :            :    *
     511                 :            :    * Even if we ignore it though, gdb will still stop if the app
     512                 :            :    * receives a SIGPIPE, which can be confusing and annoying. In `gsocket.c`,
     513                 :            :    * we can handily also set `MSG_NO_SIGNAL` / `SO_NOSIGPIPE`, but unfortunately
     514                 :            :    * there isn’t an equivalent of those for `pipe2`() FDs.
     515                 :            :    */
     516                 :         10 :   signal (SIGPIPE, SIG_IGN);
     517                 :            : #endif
     518                 :            : 
     519                 :         10 :   gobject_class->finalize = g_subprocess_finalize;
     520                 :         10 :   gobject_class->set_property = g_subprocess_set_property;
     521                 :            : 
     522                 :            :   /**
     523                 :            :    * GSubprocess:flags:
     524                 :            :    *
     525                 :            :    * Subprocess flags.
     526                 :            :    *
     527                 :            :    * Since: 2.40
     528                 :            :    */
     529                 :         10 :   g_object_class_install_property (gobject_class, PROP_FLAGS,
     530                 :            :                                    g_param_spec_flags ("flags", NULL, NULL,
     531                 :            :                                                        G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
     532                 :            :                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
     533                 :            : 
     534                 :            :   /**
     535                 :            :    * GSubprocess:argv:
     536                 :            :    *
     537                 :            :    * Argument vector.
     538                 :            :    *
     539                 :            :    * Since: 2.40
     540                 :            :    */
     541                 :         10 :   g_object_class_install_property (gobject_class, PROP_ARGV,
     542                 :            :                                    g_param_spec_boxed ("argv", NULL, NULL,
     543                 :            :                                                        G_TYPE_STRV, G_PARAM_WRITABLE |
     544                 :            :                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
     545                 :         10 : }
     546                 :            : 
     547                 :            : /**
     548                 :            :  * g_subprocess_new: (skip)
     549                 :            :  * @flags: flags that define the behaviour of the subprocess
     550                 :            :  * @error: (nullable): return location for an error, or %NULL
     551                 :            :  * @argv0: first commandline argument to pass to the subprocess
     552                 :            :  * @...:   more commandline arguments, followed by %NULL
     553                 :            :  *
     554                 :            :  * Create a new process with the given flags and varargs argument
     555                 :            :  * list.  By default, matching the g_spawn_async() defaults, the
     556                 :            :  * child's stdin will be set to the system null device, and
     557                 :            :  * stdout/stderr will be inherited from the parent.  You can use
     558                 :            :  * @flags to control this behavior.
     559                 :            :  *
     560                 :            :  * The argument list must be terminated with %NULL.
     561                 :            :  *
     562                 :            :  * Returns: A newly created #GSubprocess, or %NULL on error (and @error
     563                 :            :  *   will be set)
     564                 :            :  *
     565                 :            :  * Since: 2.40
     566                 :            :  */
     567                 :            : GSubprocess *
     568                 :          3 : g_subprocess_new (GSubprocessFlags   flags,
     569                 :            :                   GError           **error,
     570                 :            :                   const gchar       *argv0,
     571                 :            :                   ...)
     572                 :            : {
     573                 :            :   GSubprocess *result;
     574                 :            :   GPtrArray *args;
     575                 :            :   const gchar *arg;
     576                 :            :   va_list ap;
     577                 :            : 
     578                 :          3 :   g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
     579                 :          3 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     580                 :            : 
     581                 :          3 :   args = g_ptr_array_new ();
     582                 :            : 
     583                 :          3 :   va_start (ap, argv0);
     584                 :          3 :   g_ptr_array_add (args, (gchar *) argv0);
     585         [ +  + ]:          8 :   while ((arg = va_arg (ap, const gchar *)))
     586                 :          5 :     g_ptr_array_add (args, (gchar *) arg);
     587                 :          3 :   g_ptr_array_add (args, NULL);
     588                 :          3 :   va_end (ap);
     589                 :            : 
     590                 :          3 :   result = g_subprocess_newv ((const gchar * const *) args->pdata, flags, error);
     591                 :            : 
     592                 :          3 :   g_ptr_array_free (args, TRUE);
     593                 :            : 
     594                 :          3 :   return result;
     595                 :            : }
     596                 :            : 
     597                 :            : /**
     598                 :            :  * g_subprocess_newv: (rename-to g_subprocess_new)
     599                 :            :  * @argv: (array zero-terminated=1) (element-type filename): commandline arguments for the subprocess
     600                 :            :  * @flags: flags that define the behaviour of the subprocess
     601                 :            :  * @error: (nullable): return location for an error, or %NULL
     602                 :            :  *
     603                 :            :  * Create a new process with the given flags and argument list.
     604                 :            :  *
     605                 :            :  * The argument list is expected to be %NULL-terminated.
     606                 :            :  *
     607                 :            :  * Returns: A newly created #GSubprocess, or %NULL on error (and @error
     608                 :            :  *   will be set)
     609                 :            :  *
     610                 :            :  * Since: 2.40
     611                 :            :  */
     612                 :            : GSubprocess *
     613                 :         66 : g_subprocess_newv (const gchar * const  *argv,
     614                 :            :                    GSubprocessFlags      flags,
     615                 :            :                    GError              **error)
     616                 :            : {
     617                 :         66 :   g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
     618                 :            : 
     619                 :         66 :   return g_initable_new (G_TYPE_SUBPROCESS, NULL, error,
     620                 :            :                          "argv", argv,
     621                 :            :                          "flags", flags,
     622                 :            :                          NULL);
     623                 :            : }
     624                 :            : 
     625                 :            : /**
     626                 :            :  * g_subprocess_get_identifier:
     627                 :            :  * @subprocess: a #GSubprocess
     628                 :            :  *
     629                 :            :  * On UNIX, returns the process ID as a decimal string.
     630                 :            :  * On Windows, returns the result of GetProcessId() also as a string.
     631                 :            :  * If the subprocess has terminated, this will return %NULL.
     632                 :            :  *
     633                 :            :  * Returns: (nullable): the subprocess identifier, or %NULL if the subprocess
     634                 :            :  *    has terminated
     635                 :            :  * Since: 2.40
     636                 :            :  */
     637                 :            : const gchar *
     638                 :          2 : g_subprocess_get_identifier (GSubprocess *subprocess)
     639                 :            : {
     640                 :          2 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
     641                 :            : 
     642         [ +  - ]:          2 :   if (subprocess->pid)
     643                 :          2 :     return subprocess->identifier;
     644                 :            :   else
     645                 :          0 :     return NULL;
     646                 :            : }
     647                 :            : 
     648                 :            : /**
     649                 :            :  * g_subprocess_get_stdin_pipe:
     650                 :            :  * @subprocess: a #GSubprocess
     651                 :            :  *
     652                 :            :  * Gets the #GOutputStream that you can write to in order to give data
     653                 :            :  * to the stdin of @subprocess.
     654                 :            :  *
     655                 :            :  * The process must have been created with %G_SUBPROCESS_FLAGS_STDIN_PIPE and
     656                 :            :  * not %G_SUBPROCESS_FLAGS_STDIN_INHERIT, otherwise %NULL will be returned.
     657                 :            :  *
     658                 :            :  * Returns: (nullable) (transfer none): the stdout pipe
     659                 :            :  *
     660                 :            :  * Since: 2.40
     661                 :            :  **/
     662                 :            : GOutputStream *
     663                 :          8 : g_subprocess_get_stdin_pipe (GSubprocess *subprocess)
     664                 :            : {
     665                 :          8 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
     666                 :            : 
     667                 :          8 :   return subprocess->stdin_pipe;
     668                 :            : }
     669                 :            : 
     670                 :            : /**
     671                 :            :  * g_subprocess_get_stdout_pipe:
     672                 :            :  * @subprocess: a #GSubprocess
     673                 :            :  *
     674                 :            :  * Gets the #GInputStream from which to read the stdout output of
     675                 :            :  * @subprocess.
     676                 :            :  *
     677                 :            :  * The process must have been created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE,
     678                 :            :  * otherwise %NULL will be returned.
     679                 :            :  *
     680                 :            :  * Returns: (nullable) (transfer none): the stdout pipe
     681                 :            :  *
     682                 :            :  * Since: 2.40
     683                 :            :  **/
     684                 :            : GInputStream *
     685                 :         11 : g_subprocess_get_stdout_pipe (GSubprocess *subprocess)
     686                 :            : {
     687                 :         11 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
     688                 :            : 
     689                 :         11 :   return subprocess->stdout_pipe;
     690                 :            : }
     691                 :            : 
     692                 :            : /**
     693                 :            :  * g_subprocess_get_stderr_pipe:
     694                 :            :  * @subprocess: a #GSubprocess
     695                 :            :  *
     696                 :            :  * Gets the #GInputStream from which to read the stderr output of
     697                 :            :  * @subprocess.
     698                 :            :  *
     699                 :            :  * The process must have been created with %G_SUBPROCESS_FLAGS_STDERR_PIPE,
     700                 :            :  * otherwise %NULL will be returned.
     701                 :            :  *
     702                 :            :  * Returns: (nullable) (transfer none): the stderr pipe
     703                 :            :  *
     704                 :            :  * Since: 2.40
     705                 :            :  **/
     706                 :            : GInputStream *
     707                 :          0 : g_subprocess_get_stderr_pipe (GSubprocess *subprocess)
     708                 :            : {
     709                 :          0 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
     710                 :            : 
     711                 :          0 :   return subprocess->stderr_pipe;
     712                 :            : }
     713                 :            : 
     714                 :            : /* Remove the first list element containing @data, and return %TRUE. If no
     715                 :            :  * such element is found, return %FALSE. */
     716                 :            : static gboolean
     717                 :         26 : slist_remove_if_present (GSList        **list,
     718                 :            :                          gconstpointer   data)
     719                 :            : {
     720                 :            :   GSList *l, *prev;
     721                 :            : 
     722         [ +  + ]:         26 :   for (l = *list, prev = NULL; l != NULL; prev = l, l = prev->next)
     723                 :            :     {
     724         [ +  - ]:         24 :       if (l->data == data)
     725                 :            :         {
     726         [ -  + ]:         24 :           if (prev != NULL)
     727                 :          0 :             prev->next = l->next;
     728                 :            :           else
     729                 :         24 :             *list = l->next;
     730                 :            : 
     731                 :         24 :           g_slist_free_1 (l);
     732                 :            : 
     733                 :         24 :           return TRUE;
     734                 :            :         }
     735                 :            :     }
     736                 :            : 
     737                 :          2 :   return FALSE;
     738                 :            : }
     739                 :            : 
     740                 :            : static void
     741                 :         26 : g_subprocess_wait_cancelled (GCancellable *cancellable,
     742                 :            :                              gpointer      user_data)
     743                 :            : {
     744                 :         26 :   GTask *task = user_data;
     745                 :            :   GSubprocess *self;
     746                 :            :   gboolean task_was_pending;
     747                 :            : 
     748                 :         26 :   self = g_task_get_source_object (task);
     749                 :            : 
     750                 :         26 :   g_mutex_lock (&self->pending_waits_lock);
     751                 :         26 :   task_was_pending = slist_remove_if_present (&self->pending_waits, task);
     752                 :         26 :   g_mutex_unlock (&self->pending_waits_lock);
     753                 :            : 
     754         [ +  + ]:         26 :   if (task_was_pending)
     755                 :            :     {
     756                 :         24 :       g_task_return_boolean (task, FALSE);
     757                 :         24 :       g_object_unref (task);  /* ref from pending_waits */
     758                 :            :     }
     759                 :         26 : }
     760                 :            : 
     761                 :            : /**
     762                 :            :  * g_subprocess_wait_async:
     763                 :            :  * @subprocess: a #GSubprocess
     764                 :            :  * @cancellable: a #GCancellable, or %NULL
     765                 :            :  * @callback: a #GAsyncReadyCallback to call when the operation is complete
     766                 :            :  * @user_data: user_data for @callback
     767                 :            :  *
     768                 :            :  * Wait for the subprocess to terminate.
     769                 :            :  *
     770                 :            :  * This is the asynchronous version of g_subprocess_wait().
     771                 :            :  *
     772                 :            :  * Since: 2.40
     773                 :            :  */
     774                 :            : void
     775                 :         77 : g_subprocess_wait_async (GSubprocess         *subprocess,
     776                 :            :                          GCancellable        *cancellable,
     777                 :            :                          GAsyncReadyCallback  callback,
     778                 :            :                          gpointer             user_data)
     779                 :            : {
     780                 :            :   GTask *task;
     781                 :            : 
     782                 :         77 :   task = g_task_new (subprocess, cancellable, callback, user_data);
     783         [ +  - ]:         77 :   g_task_set_source_tag (task, g_subprocess_wait_async);
     784                 :            : 
     785                 :         77 :   g_mutex_lock (&subprocess->pending_waits_lock);
     786         [ +  - ]:         77 :   if (subprocess->pid)
     787                 :            :     {
     788                 :            :       /* Only bother with cancellable if we're putting it in the list.
     789                 :            :        * If not, it's going to dispatch immediately anyway and we will
     790                 :            :        * see the cancellation in the _finish().
     791                 :            :        */
     792         [ +  + ]:         77 :       if (cancellable)
     793                 :         54 :         g_signal_connect_object (cancellable, "cancelled",
     794                 :            :                                  G_CALLBACK (g_subprocess_wait_cancelled),
     795                 :            :                                  task, G_CONNECT_DEFAULT);
     796                 :            : 
     797                 :         77 :       subprocess->pending_waits = g_slist_prepend (subprocess->pending_waits, task);
     798                 :         77 :       task = NULL;
     799                 :            :     }
     800                 :         77 :   g_mutex_unlock (&subprocess->pending_waits_lock);
     801                 :            : 
     802                 :            :   /* If we still have task then it's because did_exit is already TRUE */
     803         [ -  + ]:         77 :   if (task != NULL)
     804                 :            :     {
     805                 :          0 :       g_task_return_boolean (task, TRUE);
     806                 :          0 :       g_object_unref (task);
     807                 :            :     }
     808                 :         77 : }
     809                 :            : 
     810                 :            : /**
     811                 :            :  * g_subprocess_wait_finish:
     812                 :            :  * @subprocess: a #GSubprocess
     813                 :            :  * @result: the #GAsyncResult passed to your #GAsyncReadyCallback
     814                 :            :  * @error: a pointer to a %NULL #GError, or %NULL
     815                 :            :  *
     816                 :            :  * Collects the result of a previous call to
     817                 :            :  * g_subprocess_wait_async().
     818                 :            :  *
     819                 :            :  * Returns: %TRUE if successful, or %FALSE with @error set
     820                 :            :  *
     821                 :            :  * Since: 2.40
     822                 :            :  */
     823                 :            : gboolean
     824                 :         77 : g_subprocess_wait_finish (GSubprocess   *subprocess,
     825                 :            :                           GAsyncResult  *result,
     826                 :            :                           GError       **error)
     827                 :            : {
     828                 :         77 :   return g_task_propagate_boolean (G_TASK (result), error);
     829                 :            : }
     830                 :            : 
     831                 :            : /* Some generic helpers for emulating synchronous operations using async
     832                 :            :  * operations.
     833                 :            :  */
     834                 :            : static void
     835                 :         43 : g_subprocess_sync_setup (void)
     836                 :            : {
     837                 :         43 :   g_main_context_push_thread_default (g_main_context_new ());
     838                 :         43 : }
     839                 :            : 
     840                 :            : static void
     841                 :         43 : g_subprocess_sync_done (GObject      *source_object,
     842                 :            :                         GAsyncResult *result,
     843                 :            :                         gpointer      user_data)
     844                 :            : {
     845                 :         43 :   GAsyncResult **result_ptr = user_data;
     846                 :            : 
     847                 :         43 :   *result_ptr = g_object_ref (result);
     848                 :         43 : }
     849                 :            : 
     850                 :            : static void
     851                 :         43 : g_subprocess_sync_complete (GAsyncResult **result)
     852                 :            : {
     853                 :         43 :   GMainContext *context = g_main_context_get_thread_default ();
     854                 :            : 
     855         [ +  + ]:        223 :   while (!*result)
     856                 :        180 :     g_main_context_iteration (context, TRUE);
     857                 :            : 
     858                 :         43 :   g_main_context_pop_thread_default (context);
     859                 :         43 :   g_main_context_unref (context);
     860                 :         43 : }
     861                 :            : 
     862                 :            : /**
     863                 :            :  * g_subprocess_wait:
     864                 :            :  * @subprocess: a #GSubprocess
     865                 :            :  * @cancellable: a #GCancellable
     866                 :            :  * @error: a #GError
     867                 :            :  *
     868                 :            :  * Synchronously wait for the subprocess to terminate.
     869                 :            :  *
     870                 :            :  * After the process terminates you can query its exit status with
     871                 :            :  * functions such as g_subprocess_get_if_exited() and
     872                 :            :  * g_subprocess_get_exit_status().
     873                 :            :  *
     874                 :            :  * This function does not fail in the case of the subprocess having
     875                 :            :  * abnormal termination.  See g_subprocess_wait_check() for that.
     876                 :            :  *
     877                 :            :  * Cancelling @cancellable doesn't kill the subprocess.  Call
     878                 :            :  * g_subprocess_force_exit() if it is desirable.
     879                 :            :  *
     880                 :            :  * Returns: %TRUE on success, %FALSE if @cancellable was cancelled
     881                 :            :  *
     882                 :            :  * Since: 2.40
     883                 :            :  */
     884                 :            : gboolean
     885                 :         19 : g_subprocess_wait (GSubprocess   *subprocess,
     886                 :            :                    GCancellable  *cancellable,
     887                 :            :                    GError       **error)
     888                 :            : {
     889                 :         19 :   GAsyncResult *result = NULL;
     890                 :            :   gboolean success;
     891                 :            : 
     892                 :         19 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
     893                 :            : 
     894                 :            :   /* Synchronous waits are actually the 'more difficult' case because we
     895                 :            :    * need to deal with the possibility of cancellation.  That more or
     896                 :            :    * less implies that we need a main context (to dispatch either of the
     897                 :            :    * possible reasons for the operation ending).
     898                 :            :    *
     899                 :            :    * So we make one and then do this async...
     900                 :            :    */
     901                 :            : 
     902         [ -  + ]:         19 :   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     903                 :          0 :     return FALSE;
     904                 :            : 
     905                 :            :   /* We can shortcut in the case that the process already quit (but only
     906                 :            :    * after we checked the cancellable).
     907                 :            :    */
     908         [ +  + ]:         19 :   if (subprocess->pid == 0)
     909                 :          3 :     return TRUE;
     910                 :            : 
     911                 :            :   /* Otherwise, we need to do this the long way... */
     912                 :         16 :   g_subprocess_sync_setup ();
     913                 :         16 :   g_subprocess_wait_async (subprocess, cancellable, g_subprocess_sync_done, &result);
     914                 :         16 :   g_subprocess_sync_complete (&result);
     915                 :         16 :   success = g_subprocess_wait_finish (subprocess, result, error);
     916                 :         16 :   g_object_unref (result);
     917                 :            : 
     918                 :         16 :   return success;
     919                 :            : }
     920                 :            : 
     921                 :            : /**
     922                 :            :  * g_subprocess_wait_check:
     923                 :            :  * @subprocess: a #GSubprocess
     924                 :            :  * @cancellable: a #GCancellable
     925                 :            :  * @error: a #GError
     926                 :            :  *
     927                 :            :  * Combines g_subprocess_wait() with g_spawn_check_wait_status().
     928                 :            :  *
     929                 :            :  * Returns: %TRUE on success, %FALSE if process exited abnormally, or
     930                 :            :  * @cancellable was cancelled
     931                 :            :  *
     932                 :            :  * Since: 2.40
     933                 :            :  */
     934                 :            : gboolean
     935                 :         16 : g_subprocess_wait_check (GSubprocess   *subprocess,
     936                 :            :                          GCancellable  *cancellable,
     937                 :            :                          GError       **error)
     938                 :            : {
     939   [ +  -  +  + ]:         32 :   return g_subprocess_wait (subprocess, cancellable, error) &&
     940                 :         16 :          g_spawn_check_wait_status (subprocess->status, error);
     941                 :            : }
     942                 :            : 
     943                 :            : /**
     944                 :            :  * g_subprocess_wait_check_async:
     945                 :            :  * @subprocess: a #GSubprocess
     946                 :            :  * @cancellable: a #GCancellable, or %NULL
     947                 :            :  * @callback: a #GAsyncReadyCallback to call when the operation is complete
     948                 :            :  * @user_data: user_data for @callback
     949                 :            :  *
     950                 :            :  * Combines g_subprocess_wait_async() with g_spawn_check_wait_status().
     951                 :            :  *
     952                 :            :  * This is the asynchronous version of g_subprocess_wait_check().
     953                 :            :  *
     954                 :            :  * Since: 2.40
     955                 :            :  */
     956                 :            : void
     957                 :          3 : g_subprocess_wait_check_async (GSubprocess         *subprocess,
     958                 :            :                                GCancellable        *cancellable,
     959                 :            :                                GAsyncReadyCallback  callback,
     960                 :            :                                gpointer             user_data)
     961                 :            : {
     962                 :          3 :   g_subprocess_wait_async (subprocess, cancellable, callback, user_data);
     963                 :          3 : }
     964                 :            : 
     965                 :            : /**
     966                 :            :  * g_subprocess_wait_check_finish:
     967                 :            :  * @subprocess: a #GSubprocess
     968                 :            :  * @result: the #GAsyncResult passed to your #GAsyncReadyCallback
     969                 :            :  * @error: a pointer to a %NULL #GError, or %NULL
     970                 :            :  *
     971                 :            :  * Collects the result of a previous call to
     972                 :            :  * g_subprocess_wait_check_async().
     973                 :            :  *
     974                 :            :  * Returns: %TRUE if successful, or %FALSE with @error set
     975                 :            :  *
     976                 :            :  * Since: 2.40
     977                 :            :  */
     978                 :            : gboolean
     979                 :          3 : g_subprocess_wait_check_finish (GSubprocess   *subprocess,
     980                 :            :                                 GAsyncResult  *result,
     981                 :            :                                 GError       **error)
     982                 :            : {
     983   [ +  +  +  + ]:          5 :   return g_subprocess_wait_finish (subprocess, result, error) &&
     984                 :          2 :          g_spawn_check_wait_status (subprocess->status, error);
     985                 :            : }
     986                 :            : 
     987                 :            : #ifdef G_OS_UNIX
     988                 :            : typedef struct
     989                 :            : {
     990                 :            :   GSubprocess *subprocess;
     991                 :            :   gint signalnum;
     992                 :            : } SignalRecord;
     993                 :            : 
     994                 :            : static gboolean
     995                 :          2 : g_subprocess_actually_send_signal (gpointer user_data)
     996                 :            : {
     997                 :          2 :   SignalRecord *signal_record = user_data;
     998                 :            : 
     999                 :            :   /* The pid is set to zero from the worker thread as well, so we don't
    1000                 :            :    * need to take a lock in order to prevent it from changing under us.
    1001                 :            :    */
    1002         [ +  - ]:          2 :   if (signal_record->subprocess->pid)
    1003                 :          2 :     kill (signal_record->subprocess->pid, signal_record->signalnum);
    1004                 :            : 
    1005                 :          2 :   g_object_unref (signal_record->subprocess);
    1006                 :            : 
    1007                 :          2 :   g_slice_free (SignalRecord, signal_record);
    1008                 :            : 
    1009                 :          2 :   return FALSE;
    1010                 :            : }
    1011                 :            : 
    1012                 :            : static void
    1013                 :          2 : g_subprocess_dispatch_signal (GSubprocess *subprocess,
    1014                 :            :                               gint         signalnum)
    1015                 :            : {
    1016                 :          2 :   SignalRecord signal_record = { g_object_ref (subprocess), signalnum };
    1017                 :            : 
    1018                 :          2 :   g_return_if_fail (G_IS_SUBPROCESS (subprocess));
    1019                 :            : 
    1020                 :            :   /* This MUST be a lower priority than the priority that the child
    1021                 :            :    * watch source uses in initable_init().
    1022                 :            :    *
    1023                 :            :    * Reaping processes, reporting the results back to GSubprocess and
    1024                 :            :    * sending signals is all done in the glib worker thread.  We cannot
    1025                 :            :    * have a kill() done after the reap and before the report without
    1026                 :            :    * risking killing a process that's no longer there so the kill()
    1027                 :            :    * needs to have the lower priority.
    1028                 :            :    *
    1029                 :            :    * G_PRIORITY_HIGH_IDLE is lower priority than G_PRIORITY_DEFAULT.
    1030                 :            :    */
    1031                 :          2 :   g_main_context_invoke_full (GLIB_PRIVATE_CALL (g_get_worker_context) (),
    1032                 :            :                               G_PRIORITY_HIGH_IDLE,
    1033                 :            :                               g_subprocess_actually_send_signal,
    1034                 :            :                               g_slice_dup (SignalRecord, &signal_record),
    1035                 :            :                               NULL);
    1036                 :            : }
    1037                 :            : 
    1038                 :            : /**
    1039                 :            :  * g_subprocess_send_signal:
    1040                 :            :  * @subprocess: a #GSubprocess
    1041                 :            :  * @signal_num: the signal number to send
    1042                 :            :  *
    1043                 :            :  * Sends the UNIX signal @signal_num to the subprocess, if it is still
    1044                 :            :  * running.
    1045                 :            :  *
    1046                 :            :  * This API is race-free.  If the subprocess has terminated, it will not
    1047                 :            :  * be signalled.
    1048                 :            :  *
    1049                 :            :  * This API is not available on Windows.
    1050                 :            :  *
    1051                 :            :  * Since: 2.40
    1052                 :            :  **/
    1053                 :            : void
    1054                 :          1 : g_subprocess_send_signal (GSubprocess *subprocess,
    1055                 :            :                           gint         signal_num)
    1056                 :            : {
    1057                 :          1 :   g_return_if_fail (G_IS_SUBPROCESS (subprocess));
    1058                 :            : 
    1059                 :          1 :   g_subprocess_dispatch_signal (subprocess, signal_num);
    1060                 :            : }
    1061                 :            : #endif
    1062                 :            : 
    1063                 :            : /**
    1064                 :            :  * g_subprocess_force_exit:
    1065                 :            :  * @subprocess: a #GSubprocess
    1066                 :            :  *
    1067                 :            :  * Use an operating-system specific method to attempt an immediate,
    1068                 :            :  * forceful termination of the process.  There is no mechanism to
    1069                 :            :  * determine whether or not the request itself was successful;
    1070                 :            :  * however, you can use g_subprocess_wait() to monitor the status of
    1071                 :            :  * the process after calling this function.
    1072                 :            :  *
    1073                 :            :  * On Unix, this function sends %SIGKILL.
    1074                 :            :  *
    1075                 :            :  * Since: 2.40
    1076                 :            :  **/
    1077                 :            : void
    1078                 :          1 : g_subprocess_force_exit (GSubprocess *subprocess)
    1079                 :            : {
    1080                 :          1 :   g_return_if_fail (G_IS_SUBPROCESS (subprocess));
    1081                 :            : 
    1082                 :            : #ifdef G_OS_UNIX
    1083                 :          1 :   g_subprocess_dispatch_signal (subprocess, SIGKILL);
    1084                 :            : #else
    1085                 :            :   TerminateProcess (subprocess->pid, 1);
    1086                 :            : #endif
    1087                 :            : }
    1088                 :            : 
    1089                 :            : /**
    1090                 :            :  * g_subprocess_get_status:
    1091                 :            :  * @subprocess: a #GSubprocess
    1092                 :            :  *
    1093                 :            :  * Gets the raw status code of the process, as from waitpid().
    1094                 :            :  *
    1095                 :            :  * This value has no particular meaning, but it can be used with the
    1096                 :            :  * macros defined by the system headers such as WIFEXITED.  It can also
    1097                 :            :  * be used with g_spawn_check_wait_status().
    1098                 :            :  *
    1099                 :            :  * It is more likely that you want to use g_subprocess_get_if_exited()
    1100                 :            :  * followed by g_subprocess_get_exit_status().
    1101                 :            :  *
    1102                 :            :  * It is an error to call this function before g_subprocess_wait() has
    1103                 :            :  * returned.
    1104                 :            :  *
    1105                 :            :  * Returns: the (meaningless) waitpid() exit status from the kernel
    1106                 :            :  *
    1107                 :            :  * Since: 2.40
    1108                 :            :  **/
    1109                 :            : gint
    1110                 :          5 : g_subprocess_get_status (GSubprocess *subprocess)
    1111                 :            : {
    1112                 :          5 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1113                 :          5 :   g_return_val_if_fail (subprocess->pid == 0, FALSE);
    1114                 :            : 
    1115                 :          5 :   return subprocess->status;
    1116                 :            : }
    1117                 :            : 
    1118                 :            : /**
    1119                 :            :  * g_subprocess_get_successful:
    1120                 :            :  * @subprocess: a #GSubprocess
    1121                 :            :  *
    1122                 :            :  * Checks if the process was "successful".  A process is considered
    1123                 :            :  * successful if it exited cleanly with an exit status of 0, either by
    1124                 :            :  * way of the exit() system call or return from main().
    1125                 :            :  *
    1126                 :            :  * It is an error to call this function before g_subprocess_wait() has
    1127                 :            :  * returned.
    1128                 :            :  *
    1129                 :            :  * Returns: %TRUE if the process exited cleanly with a exit status of 0
    1130                 :            :  *
    1131                 :            :  * Since: 2.40
    1132                 :            :  **/
    1133                 :            : gboolean
    1134                 :          2 : g_subprocess_get_successful (GSubprocess *subprocess)
    1135                 :            : {
    1136                 :          2 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1137                 :          2 :   g_return_val_if_fail (subprocess->pid == 0, FALSE);
    1138                 :            : 
    1139                 :            : #ifdef G_OS_UNIX
    1140   [ +  +  +  - ]:          2 :   return WIFEXITED (subprocess->status) && WEXITSTATUS (subprocess->status) == 0;
    1141                 :            : #else
    1142                 :            :   return subprocess->status == 0;
    1143                 :            : #endif
    1144                 :            : }
    1145                 :            : 
    1146                 :            : /**
    1147                 :            :  * g_subprocess_get_if_exited:
    1148                 :            :  * @subprocess: a #GSubprocess
    1149                 :            :  *
    1150                 :            :  * Check if the given subprocess exited normally (ie: by way of exit()
    1151                 :            :  * or return from main()).
    1152                 :            :  *
    1153                 :            :  * This is equivalent to the system WIFEXITED macro.
    1154                 :            :  *
    1155                 :            :  * It is an error to call this function before g_subprocess_wait() has
    1156                 :            :  * returned.
    1157                 :            :  *
    1158                 :            :  * Returns: %TRUE if the case of a normal exit
    1159                 :            :  *
    1160                 :            :  * Since: 2.40
    1161                 :            :  **/
    1162                 :            : gboolean
    1163                 :          1 : g_subprocess_get_if_exited (GSubprocess *subprocess)
    1164                 :            : {
    1165                 :          1 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1166                 :          1 :   g_return_val_if_fail (subprocess->pid == 0, FALSE);
    1167                 :            : 
    1168                 :            : #ifdef G_OS_UNIX
    1169                 :          1 :   return WIFEXITED (subprocess->status);
    1170                 :            : #else
    1171                 :            :   return TRUE;
    1172                 :            : #endif
    1173                 :            : }
    1174                 :            : 
    1175                 :            : /**
    1176                 :            :  * g_subprocess_get_exit_status:
    1177                 :            :  * @subprocess: a #GSubprocess
    1178                 :            :  *
    1179                 :            :  * Check the exit status of the subprocess, given that it exited
    1180                 :            :  * normally.  This is the value passed to the exit() system call or the
    1181                 :            :  * return value from main.
    1182                 :            :  *
    1183                 :            :  * This is equivalent to the system WEXITSTATUS macro.
    1184                 :            :  *
    1185                 :            :  * It is an error to call this function before g_subprocess_wait() and
    1186                 :            :  * unless g_subprocess_get_if_exited() returned %TRUE.
    1187                 :            :  *
    1188                 :            :  * Returns: the exit status
    1189                 :            :  *
    1190                 :            :  * Since: 2.40
    1191                 :            :  **/
    1192                 :            : gint
    1193                 :          1 : g_subprocess_get_exit_status (GSubprocess *subprocess)
    1194                 :            : {
    1195                 :          1 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), 1);
    1196                 :          1 :   g_return_val_if_fail (subprocess->pid == 0, 1);
    1197                 :            : 
    1198                 :            : #ifdef G_OS_UNIX
    1199                 :          1 :   g_return_val_if_fail (WIFEXITED (subprocess->status), 1);
    1200                 :            : 
    1201                 :          1 :   return WEXITSTATUS (subprocess->status);
    1202                 :            : #else
    1203                 :            :   return subprocess->status;
    1204                 :            : #endif
    1205                 :            : }
    1206                 :            : 
    1207                 :            : /**
    1208                 :            :  * g_subprocess_get_if_signaled:
    1209                 :            :  * @subprocess: a #GSubprocess
    1210                 :            :  *
    1211                 :            :  * Check if the given subprocess terminated in response to a signal.
    1212                 :            :  *
    1213                 :            :  * This is equivalent to the system WIFSIGNALED macro.
    1214                 :            :  *
    1215                 :            :  * It is an error to call this function before g_subprocess_wait() has
    1216                 :            :  * returned.
    1217                 :            :  *
    1218                 :            :  * Returns: %TRUE if the case of termination due to a signal
    1219                 :            :  *
    1220                 :            :  * Since: 2.40
    1221                 :            :  **/
    1222                 :            : gboolean
    1223                 :          2 : g_subprocess_get_if_signaled (GSubprocess *subprocess)
    1224                 :            : {
    1225                 :          2 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1226                 :          2 :   g_return_val_if_fail (subprocess->pid == 0, FALSE);
    1227                 :            : 
    1228                 :            : #ifdef G_OS_UNIX
    1229                 :          2 :   return WIFSIGNALED (subprocess->status);
    1230                 :            : #else
    1231                 :            :   return FALSE;
    1232                 :            : #endif
    1233                 :            : }
    1234                 :            : 
    1235                 :            : /**
    1236                 :            :  * g_subprocess_get_term_sig:
    1237                 :            :  * @subprocess: a #GSubprocess
    1238                 :            :  *
    1239                 :            :  * Get the signal number that caused the subprocess to terminate, given
    1240                 :            :  * that it terminated due to a signal.
    1241                 :            :  *
    1242                 :            :  * This is equivalent to the system WTERMSIG macro.
    1243                 :            :  *
    1244                 :            :  * It is an error to call this function before g_subprocess_wait() and
    1245                 :            :  * unless g_subprocess_get_if_signaled() returned %TRUE.
    1246                 :            :  *
    1247                 :            :  * Returns: the signal causing termination
    1248                 :            :  *
    1249                 :            :  * Since: 2.40
    1250                 :            :  **/
    1251                 :            : gint
    1252                 :          2 : g_subprocess_get_term_sig (GSubprocess *subprocess)
    1253                 :            : {
    1254                 :          2 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), 0);
    1255                 :          2 :   g_return_val_if_fail (subprocess->pid == 0, 0);
    1256                 :            : 
    1257                 :            : #ifdef G_OS_UNIX
    1258                 :          2 :   g_return_val_if_fail (WIFSIGNALED (subprocess->status), 0);
    1259                 :            : 
    1260                 :          2 :   return WTERMSIG (subprocess->status);
    1261                 :            : #else
    1262                 :            :   g_critical ("g_subprocess_get_term_sig() called on Windows, where "
    1263                 :            :               "g_subprocess_get_if_signaled() always returns FALSE...");
    1264                 :            :   return 0;
    1265                 :            : #endif
    1266                 :            : }
    1267                 :            : 
    1268                 :            : /*< private >*/
    1269                 :            : void
    1270                 :         21 : g_subprocess_set_launcher (GSubprocess         *subprocess,
    1271                 :            :                            GSubprocessLauncher *launcher)
    1272                 :            : {
    1273                 :         21 :   subprocess->launcher = launcher;
    1274                 :         21 : }
    1275                 :            : 
    1276                 :            : 
    1277                 :            : /* g_subprocess_communicate implementation below:
    1278                 :            :  *
    1279                 :            :  * This is a tough problem.  We have to watch 5 things at the same time:
    1280                 :            :  *
    1281                 :            :  *  - writing to stdin made progress
    1282                 :            :  *  - reading from stdout made progress
    1283                 :            :  *  - reading from stderr made progress
    1284                 :            :  *  - process terminated
    1285                 :            :  *  - cancellable being cancelled by caller
    1286                 :            :  *
    1287                 :            :  * We use a GMainContext for all of these (either as async function
    1288                 :            :  * calls or as a GSource (in the case of the cancellable).  That way at
    1289                 :            :  * least we don't have to worry about threading.
    1290                 :            :  *
    1291                 :            :  * For the sync case we use the usual trick of creating a private main
    1292                 :            :  * context and iterating it until completion.
    1293                 :            :  *
    1294                 :            :  * It's very possible that the process will dump a lot of data to stdout
    1295                 :            :  * just before it quits, so we can easily have data to read from stdout
    1296                 :            :  * and see the process has terminated at the same time.  We want to make
    1297                 :            :  * sure that we read all of the data from the pipes first, though, so we
    1298                 :            :  * do IO operations at a higher priority than the wait operation (which
    1299                 :            :  * is at G_IO_PRIORITY_DEFAULT).  Even in the case that we have to do
    1300                 :            :  * multiple reads to get this data, the pipe() will always be polling
    1301                 :            :  * as ready and with the async result for the read at a higher priority,
    1302                 :            :  * the main context will not dispatch the completion for the wait().
    1303                 :            :  *
    1304                 :            :  * We keep our own private GCancellable.  In the event that any of the
    1305                 :            :  * above suffers from an error condition (including the user cancelling
    1306                 :            :  * their cancellable) we immediately dispatch the GTask with the error
    1307                 :            :  * result and fire our cancellable to cleanup any pending operations.
    1308                 :            :  * In the case that the error is that the user's cancellable was fired,
    1309                 :            :  * it's vaguely wasteful to report an error because GTask will handle
    1310                 :            :  * this automatically, so we just return FALSE.
    1311                 :            :  *
    1312                 :            :  * We let each pending sub-operation take a ref on the GTask of the
    1313                 :            :  * communicate operation.  We have to be careful that we don't report
    1314                 :            :  * the task completion more than once, though, so we keep a flag for
    1315                 :            :  * that.
    1316                 :            :  */
    1317                 :            : typedef struct
    1318                 :            : {
    1319                 :            :   const gchar *stdin_data;
    1320                 :            :   gsize stdin_length;
    1321                 :            :   gsize stdin_offset;
    1322                 :            : 
    1323                 :            :   gboolean add_nul;
    1324                 :            : 
    1325                 :            :   GInputStream *stdin_buf;
    1326                 :            :   GMemoryOutputStream *stdout_buf;
    1327                 :            :   GMemoryOutputStream *stderr_buf;
    1328                 :            : 
    1329                 :            :   GCancellable *cancellable;
    1330                 :            :   GSource      *cancellable_source;
    1331                 :            : 
    1332                 :            :   guint         outstanding_ops;
    1333                 :            :   gboolean      reported_error;
    1334                 :            : } CommunicateState;
    1335                 :            : 
    1336                 :            : static void
    1337                 :        125 : g_subprocess_communicate_made_progress (GObject      *source_object,
    1338                 :            :                                         GAsyncResult *result,
    1339                 :            :                                         gpointer      user_data)
    1340                 :            : {
    1341                 :            :   CommunicateState *state;
    1342                 :            :   GSubprocess *subprocess;
    1343                 :        125 :   GError *error = NULL;
    1344                 :            :   gpointer source;
    1345                 :            :   GTask *task;
    1346                 :            : 
    1347                 :        125 :   g_assert (source_object != NULL);
    1348                 :            : 
    1349                 :        125 :   task = user_data;
    1350                 :        125 :   subprocess = g_task_get_source_object (task);
    1351                 :        125 :   state = g_task_get_task_data (task);
    1352                 :        125 :   source = source_object;
    1353                 :            : 
    1354                 :        125 :   state->outstanding_ops--;
    1355                 :            : 
    1356         [ +  + ]:        125 :   if (source == subprocess->stdin_pipe ||
    1357         [ +  + ]:         86 :       source == state->stdout_buf ||
    1358         [ +  + ]:         64 :       source == state->stderr_buf)
    1359                 :            :     {
    1360         [ +  + ]:         73 :       if (g_output_stream_splice_finish ((GOutputStream*) source, result, &error) == -1)
    1361                 :         22 :         goto out;
    1362                 :            : 
    1363         [ +  + ]:         51 :       if (source == state->stdout_buf ||
    1364         [ +  + ]:         35 :           source == state->stderr_buf)
    1365                 :            :         {
    1366                 :            :           /* This is a memory stream, so it can't be cancelled or return
    1367                 :            :            * an error really.
    1368                 :            :            */
    1369         [ +  + ]:         24 :           if (state->add_nul)
    1370                 :            :             {
    1371                 :            :               gsize bytes_written;
    1372         [ -  + ]:         14 :               if (!g_output_stream_write_all (source, "\0", 1, &bytes_written,
    1373                 :            :                                               NULL, &error))
    1374                 :          0 :                 goto out;
    1375                 :            :             }
    1376         [ -  + ]:         24 :           if (!g_output_stream_close (source, NULL, &error))
    1377                 :          0 :             goto out;
    1378                 :            :         }
    1379                 :            :     }
    1380         [ +  - ]:         52 :   else if (source == subprocess)
    1381                 :            :     {
    1382                 :         52 :       (void) g_subprocess_wait_finish (subprocess, result, &error);
    1383                 :            :     }
    1384                 :            :   else
    1385                 :            :     g_assert_not_reached ();
    1386                 :            : 
    1387                 :        125 :  out:
    1388         [ +  + ]:        125 :   if (error)
    1389                 :            :     {
    1390                 :            :       /* Only report the first error we see.
    1391                 :            :        *
    1392                 :            :        * We might be seeing an error as a result of the cancellation
    1393                 :            :        * done when the process quits.
    1394                 :            :        */
    1395         [ +  + ]:         46 :       if (!state->reported_error)
    1396                 :            :         {
    1397                 :         24 :           state->reported_error = TRUE;
    1398                 :         24 :           g_cancellable_cancel (state->cancellable);
    1399                 :         24 :           g_task_return_error (task, error);
    1400                 :            :         }
    1401                 :            :       else
    1402                 :         22 :         g_error_free (error);
    1403                 :            :     }
    1404         [ +  + ]:         79 :   else if (state->outstanding_ops == 0)
    1405                 :            :     {
    1406                 :         28 :       g_task_return_boolean (task, TRUE);
    1407                 :            :     }
    1408                 :            : 
    1409                 :            :   /* And drop the original ref */
    1410                 :        125 :   g_object_unref (task);
    1411                 :        125 : }
    1412                 :            : 
    1413                 :            : static gboolean
    1414                 :         24 : g_subprocess_communicate_cancelled (GCancellable *cancellable,
    1415                 :            :                                     gpointer      user_data)
    1416                 :            : {
    1417                 :         24 :   CommunicateState *state = user_data;
    1418                 :            : 
    1419                 :         24 :   g_cancellable_cancel (state->cancellable);
    1420                 :            : 
    1421                 :         24 :   return FALSE;
    1422                 :            : }
    1423                 :            : 
    1424                 :            : static void
    1425                 :         40 : g_subprocess_communicate_state_free (gpointer data)
    1426                 :            : {
    1427                 :         40 :   CommunicateState *state = data;
    1428                 :            : 
    1429                 :         40 :   g_clear_object (&state->cancellable);
    1430                 :         40 :   g_clear_object (&state->stdin_buf);
    1431                 :         40 :   g_clear_object (&state->stdout_buf);
    1432                 :         40 :   g_clear_object (&state->stderr_buf);
    1433                 :            : 
    1434         [ +  + ]:         40 :   if (state->cancellable_source)
    1435                 :            :     {
    1436                 :         12 :       g_source_destroy (state->cancellable_source);
    1437                 :         12 :       g_source_unref (state->cancellable_source);
    1438                 :            :     }
    1439                 :            : 
    1440                 :         40 :   g_slice_free (CommunicateState, state);
    1441                 :         40 : }
    1442                 :            : 
    1443                 :            : static CommunicateState *
    1444                 :         52 : g_subprocess_communicate_internal (GSubprocess         *subprocess,
    1445                 :            :                                    gboolean             add_nul,
    1446                 :            :                                    GBytes              *stdin_buf,
    1447                 :            :                                    GCancellable        *cancellable,
    1448                 :            :                                    GAsyncReadyCallback  callback,
    1449                 :            :                                    gpointer             user_data)
    1450                 :            : {
    1451                 :            :   CommunicateState *state;
    1452                 :            :   GTask *task;
    1453                 :            : 
    1454                 :         52 :   task = g_task_new (subprocess, cancellable, callback, user_data);
    1455         [ +  - ]:         52 :   g_task_set_source_tag (task, g_subprocess_communicate_internal);
    1456                 :            : 
    1457                 :         52 :   state = g_slice_new0 (CommunicateState);
    1458                 :         52 :   g_task_set_task_data (task, state, g_subprocess_communicate_state_free);
    1459                 :            : 
    1460                 :         52 :   state->cancellable = g_cancellable_new ();
    1461                 :         52 :   state->add_nul = add_nul;
    1462                 :            : 
    1463         [ +  + ]:         52 :   if (cancellable)
    1464                 :            :     {
    1465                 :         24 :       state->cancellable_source = g_cancellable_source_new (cancellable);
    1466                 :            :       /* No ref held here, but we unref the source from state's free function */
    1467                 :         24 :       g_source_set_callback (state->cancellable_source,
    1468                 :            :                              G_SOURCE_FUNC (g_subprocess_communicate_cancelled),
    1469                 :            :                              state, NULL);
    1470                 :         24 :       g_source_attach (state->cancellable_source, g_main_context_get_thread_default ());
    1471                 :            :     }
    1472                 :            : 
    1473         [ +  + ]:         52 :   if (subprocess->stdin_pipe)
    1474                 :            :     {
    1475                 :         51 :       g_assert (stdin_buf != NULL);
    1476                 :            : 
    1477                 :            : #ifdef G_OS_UNIX
    1478                 :            :       /* We're doing async writes to the pipe, and the async write mechanism assumes
    1479                 :            :        * that streams polling as writable do SOME progress (possibly partial) and then
    1480                 :            :        * stop, but never block.
    1481                 :            :        *
    1482                 :            :        * However, for blocking pipes, unix will return writable if there is *any* space left
    1483                 :            :        * but still block until the full buffer size is available before returning from write.
    1484                 :            :        * So, to avoid async blocking on the main loop we make this non-blocking here.
    1485                 :            :        *
    1486                 :            :        * It should be safe to change the fd because we're the only user at this point as
    1487                 :            :        * per the g_subprocess_communicate() docs, and all the code called by this function
    1488                 :            :        * properly handles non-blocking fds.
    1489                 :            :        */
    1490                 :         51 :       g_unix_set_fd_nonblocking (g_unix_output_stream_get_fd (G_UNIX_OUTPUT_STREAM (subprocess->stdin_pipe)), TRUE, NULL);
    1491                 :            : #endif
    1492                 :            : 
    1493                 :         51 :       state->stdin_buf = g_memory_input_stream_new_from_bytes (stdin_buf);
    1494                 :         51 :       g_output_stream_splice_async (subprocess->stdin_pipe, (GInputStream*)state->stdin_buf,
    1495                 :            :                                     G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
    1496                 :            :                                     G_PRIORITY_DEFAULT, state->cancellable,
    1497                 :            :                                     g_subprocess_communicate_made_progress, g_object_ref (task));
    1498                 :         51 :       state->outstanding_ops++;
    1499                 :            :     }
    1500                 :            : 
    1501         [ +  + ]:         52 :   if (subprocess->stdout_pipe)
    1502                 :            :     {
    1503                 :         28 :       state->stdout_buf = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
    1504                 :         28 :       g_output_stream_splice_async ((GOutputStream*)state->stdout_buf, subprocess->stdout_pipe,
    1505                 :            :                                     G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
    1506                 :            :                                     G_PRIORITY_DEFAULT, state->cancellable,
    1507                 :            :                                     g_subprocess_communicate_made_progress, g_object_ref (task));
    1508                 :         28 :       state->outstanding_ops++;
    1509                 :            :     }
    1510                 :            : 
    1511         [ +  + ]:         52 :   if (subprocess->stderr_pipe)
    1512                 :            :     {
    1513                 :         16 :       state->stderr_buf = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
    1514                 :         16 :       g_output_stream_splice_async ((GOutputStream*)state->stderr_buf, subprocess->stderr_pipe,
    1515                 :            :                                     G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
    1516                 :            :                                     G_PRIORITY_DEFAULT, state->cancellable,
    1517                 :            :                                     g_subprocess_communicate_made_progress, g_object_ref (task));
    1518                 :         16 :       state->outstanding_ops++;
    1519                 :            :     }
    1520                 :            : 
    1521                 :         52 :   g_subprocess_wait_async (subprocess, state->cancellable,
    1522                 :            :                            g_subprocess_communicate_made_progress, g_object_ref (task));
    1523                 :         52 :   state->outstanding_ops++;
    1524                 :            : 
    1525                 :         52 :   g_object_unref (task);
    1526                 :         52 :   return state;
    1527                 :            : }
    1528                 :            : 
    1529                 :            : /**
    1530                 :            :  * g_subprocess_communicate:
    1531                 :            :  * @subprocess: a #GSubprocess
    1532                 :            :  * @stdin_buf: (nullable): data to send to the stdin of the subprocess, or %NULL
    1533                 :            :  * @cancellable: a #GCancellable
    1534                 :            :  * @stdout_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stdout
    1535                 :            :  * @stderr_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stderr
    1536                 :            :  * @error: a pointer to a %NULL #GError pointer, or %NULL
    1537                 :            :  *
    1538                 :            :  * Communicate with the subprocess until it terminates, and all input
    1539                 :            :  * and output has been completed.
    1540                 :            :  *
    1541                 :            :  * If @stdin_buf is given, the subprocess must have been created with
    1542                 :            :  * %G_SUBPROCESS_FLAGS_STDIN_PIPE.  The given data is fed to the
    1543                 :            :  * stdin of the subprocess and the pipe is closed (ie: EOF).
    1544                 :            :  *
    1545                 :            :  * At the same time (as not to cause blocking when dealing with large
    1546                 :            :  * amounts of data), if %G_SUBPROCESS_FLAGS_STDOUT_PIPE or
    1547                 :            :  * %G_SUBPROCESS_FLAGS_STDERR_PIPE were used, reads from those
    1548                 :            :  * streams.  The data that was read is returned in @stdout and/or
    1549                 :            :  * the @stderr.
    1550                 :            :  *
    1551                 :            :  * If the subprocess was created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE,
    1552                 :            :  * @stdout_buf will contain the data read from stdout.  Otherwise, for
    1553                 :            :  * subprocesses not created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE,
    1554                 :            :  * @stdout_buf will be set to %NULL.  Similar provisions apply to
    1555                 :            :  * @stderr_buf and %G_SUBPROCESS_FLAGS_STDERR_PIPE.
    1556                 :            :  *
    1557                 :            :  * As usual, any output variable may be given as %NULL to ignore it.
    1558                 :            :  *
    1559                 :            :  * If you desire the stdout and stderr data to be interleaved, create
    1560                 :            :  * the subprocess with %G_SUBPROCESS_FLAGS_STDOUT_PIPE and
    1561                 :            :  * %G_SUBPROCESS_FLAGS_STDERR_MERGE.  The merged result will be returned
    1562                 :            :  * in @stdout_buf and @stderr_buf will be set to %NULL.
    1563                 :            :  *
    1564                 :            :  * In case of any error (including cancellation), %FALSE will be
    1565                 :            :  * returned with @error set.  Some or all of the stdin data may have
    1566                 :            :  * been written.  Any stdout or stderr data that has been read will be
    1567                 :            :  * discarded. None of the out variables (aside from @error) will have
    1568                 :            :  * been set to anything in particular and should not be inspected.
    1569                 :            :  *
    1570                 :            :  * In the case that %TRUE is returned, the subprocess has exited and the
    1571                 :            :  * exit status inspection APIs (eg: g_subprocess_get_if_exited(),
    1572                 :            :  * g_subprocess_get_exit_status()) may be used.
    1573                 :            :  *
    1574                 :            :  * You should not attempt to use any of the subprocess pipes after
    1575                 :            :  * starting this function, since they may be left in strange states,
    1576                 :            :  * even if the operation was cancelled.  You should especially not
    1577                 :            :  * attempt to interact with the pipes while the operation is in progress
    1578                 :            :  * (either from another thread or if using the asynchronous version).
    1579                 :            :  *
    1580                 :            :  * Returns: %TRUE if successful
    1581                 :            :  *
    1582                 :            :  * Since: 2.40
    1583                 :            :  **/
    1584                 :            : gboolean
    1585                 :         12 : g_subprocess_communicate (GSubprocess   *subprocess,
    1586                 :            :                           GBytes        *stdin_buf,
    1587                 :            :                           GCancellable  *cancellable,
    1588                 :            :                           GBytes       **stdout_buf,
    1589                 :            :                           GBytes       **stderr_buf,
    1590                 :            :                           GError       **error)
    1591                 :            : {
    1592                 :         12 :   GAsyncResult *result = NULL;
    1593                 :            :   gboolean success;
    1594                 :            : 
    1595                 :         12 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1596                 :         12 :   g_return_val_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE), FALSE);
    1597                 :         12 :   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
    1598                 :         12 :   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1599                 :            : 
    1600                 :         12 :   g_subprocess_sync_setup ();
    1601                 :         12 :   g_subprocess_communicate_internal (subprocess, FALSE, stdin_buf, cancellable,
    1602                 :            :                                      g_subprocess_sync_done, &result);
    1603                 :         12 :   g_subprocess_sync_complete (&result);
    1604                 :         12 :   success = g_subprocess_communicate_finish (subprocess, result, stdout_buf, stderr_buf, error);
    1605                 :         12 :   g_object_unref (result);
    1606                 :            : 
    1607                 :         12 :   return success;
    1608                 :            : }
    1609                 :            : 
    1610                 :            : /**
    1611                 :            :  * g_subprocess_communicate_async:
    1612                 :            :  * @subprocess: Self
    1613                 :            :  * @stdin_buf: (nullable): Input data, or %NULL
    1614                 :            :  * @cancellable: (nullable): Cancellable
    1615                 :            :  * @callback: Callback
    1616                 :            :  * @user_data: User data
    1617                 :            :  *
    1618                 :            :  * Asynchronous version of g_subprocess_communicate().  Complete
    1619                 :            :  * invocation with g_subprocess_communicate_finish().
    1620                 :            :  */
    1621                 :            : void
    1622                 :         12 : g_subprocess_communicate_async (GSubprocess         *subprocess,
    1623                 :            :                                 GBytes              *stdin_buf,
    1624                 :            :                                 GCancellable        *cancellable,
    1625                 :            :                                 GAsyncReadyCallback  callback,
    1626                 :            :                                 gpointer             user_data)
    1627                 :            : {
    1628                 :         12 :   g_return_if_fail (G_IS_SUBPROCESS (subprocess));
    1629                 :         12 :   g_return_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE));
    1630                 :         12 :   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
    1631                 :            : 
    1632                 :         12 :   g_subprocess_communicate_internal (subprocess, FALSE, stdin_buf, cancellable, callback, user_data);
    1633                 :            : }
    1634                 :            : 
    1635                 :            : /**
    1636                 :            :  * g_subprocess_communicate_finish:
    1637                 :            :  * @subprocess: Self
    1638                 :            :  * @result: Result
    1639                 :            :  * @stdout_buf: (out) (nullable) (optional) (transfer full): Return location for stdout data
    1640                 :            :  * @stderr_buf: (out) (nullable) (optional) (transfer full): Return location for stderr data
    1641                 :            :  * @error: Error
    1642                 :            :  *
    1643                 :            :  * Complete an invocation of g_subprocess_communicate_async().
    1644                 :            :  */
    1645                 :            : gboolean
    1646                 :         24 : g_subprocess_communicate_finish (GSubprocess   *subprocess,
    1647                 :            :                                  GAsyncResult  *result,
    1648                 :            :                                  GBytes       **stdout_buf,
    1649                 :            :                                  GBytes       **stderr_buf,
    1650                 :            :                                  GError       **error)
    1651                 :            : {
    1652                 :            :   gboolean success;
    1653                 :            :   CommunicateState *state;
    1654                 :            : 
    1655                 :         24 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1656                 :         24 :   g_return_val_if_fail (g_task_is_valid (result, subprocess), FALSE);
    1657                 :         24 :   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1658                 :            : 
    1659                 :         24 :   g_object_ref (result);
    1660                 :            : 
    1661                 :         24 :   state = g_task_get_task_data ((GTask*)result);
    1662                 :         24 :   success = g_task_propagate_boolean ((GTask*)result, error);
    1663                 :            : 
    1664         [ +  + ]:         24 :   if (success)
    1665                 :            :     {
    1666         [ +  - ]:         12 :       if (stdout_buf)
    1667         [ +  + ]:         12 :         *stdout_buf = (state->stdout_buf != NULL) ? g_memory_output_stream_steal_as_bytes (state->stdout_buf) : NULL;
    1668         [ +  - ]:         12 :       if (stderr_buf)
    1669         [ +  + ]:         12 :         *stderr_buf = (state->stderr_buf != NULL) ? g_memory_output_stream_steal_as_bytes (state->stderr_buf) : NULL;
    1670                 :            :     }
    1671                 :            : 
    1672                 :         24 :   g_object_unref (result);
    1673                 :         24 :   return success;
    1674                 :            : }
    1675                 :            : 
    1676                 :            : /**
    1677                 :            :  * g_subprocess_communicate_utf8:
    1678                 :            :  * @subprocess: a #GSubprocess
    1679                 :            :  * @stdin_buf: (nullable): data to send to the stdin of the subprocess, or %NULL
    1680                 :            :  * @cancellable: a #GCancellable
    1681                 :            :  * @stdout_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stdout
    1682                 :            :  * @stderr_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stderr
    1683                 :            :  * @error: a pointer to a %NULL #GError pointer, or %NULL
    1684                 :            :  *
    1685                 :            :  * Like g_subprocess_communicate(), but validates the output of the
    1686                 :            :  * process as UTF-8, and returns it as a regular NUL terminated string.
    1687                 :            :  *
    1688                 :            :  * On error, @stdout_buf and @stderr_buf will be set to undefined values and
    1689                 :            :  * should not be used.
    1690                 :            :  */
    1691                 :            : gboolean
    1692                 :         15 : g_subprocess_communicate_utf8 (GSubprocess   *subprocess,
    1693                 :            :                                const char    *stdin_buf,
    1694                 :            :                                GCancellable  *cancellable,
    1695                 :            :                                char         **stdout_buf,
    1696                 :            :                                char         **stderr_buf,
    1697                 :            :                                GError       **error)
    1698                 :            : {
    1699                 :         15 :   GAsyncResult *result = NULL;
    1700                 :            :   gboolean success;
    1701                 :            :   GBytes *stdin_bytes;
    1702                 :         15 :   size_t stdin_buf_len = 0;
    1703                 :            : 
    1704                 :         15 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1705                 :         15 :   g_return_val_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE), FALSE);
    1706                 :         15 :   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
    1707                 :         15 :   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1708                 :            : 
    1709         [ +  + ]:         15 :   if (stdin_buf != NULL)
    1710                 :         14 :     stdin_buf_len = strlen (stdin_buf);
    1711                 :         15 :   stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len);
    1712                 :            : 
    1713                 :         15 :   g_subprocess_sync_setup ();
    1714                 :         15 :   g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable,
    1715                 :            :                                      g_subprocess_sync_done, &result);
    1716                 :         15 :   g_subprocess_sync_complete (&result);
    1717                 :         15 :   success = g_subprocess_communicate_utf8_finish (subprocess, result, stdout_buf, stderr_buf, error);
    1718                 :         15 :   g_object_unref (result);
    1719                 :            : 
    1720                 :         15 :   g_bytes_unref (stdin_bytes);
    1721                 :         15 :   return success;
    1722                 :            : }
    1723                 :            : 
    1724                 :            : /**
    1725                 :            :  * g_subprocess_communicate_utf8_async:
    1726                 :            :  * @subprocess: Self
    1727                 :            :  * @stdin_buf: (nullable): Input data, or %NULL
    1728                 :            :  * @cancellable: Cancellable
    1729                 :            :  * @callback: Callback
    1730                 :            :  * @user_data: User data
    1731                 :            :  *
    1732                 :            :  * Asynchronous version of g_subprocess_communicate_utf8().  Complete
    1733                 :            :  * invocation with g_subprocess_communicate_utf8_finish().
    1734                 :            :  */
    1735                 :            : void
    1736                 :         13 : g_subprocess_communicate_utf8_async (GSubprocess         *subprocess,
    1737                 :            :                                      const char          *stdin_buf,
    1738                 :            :                                      GCancellable        *cancellable,
    1739                 :            :                                      GAsyncReadyCallback  callback,
    1740                 :            :                                      gpointer             user_data)
    1741                 :            : {
    1742                 :            :   GBytes *stdin_bytes;
    1743                 :         13 :   size_t stdin_buf_len = 0;
    1744                 :            : 
    1745                 :         13 :   g_return_if_fail (G_IS_SUBPROCESS (subprocess));
    1746                 :         13 :   g_return_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE));
    1747                 :         13 :   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
    1748                 :            : 
    1749         [ +  - ]:         13 :   if (stdin_buf != NULL)
    1750                 :         13 :     stdin_buf_len = strlen (stdin_buf);
    1751                 :         13 :   stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len);
    1752                 :            : 
    1753                 :         13 :   g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable, callback, user_data);
    1754                 :            : 
    1755                 :         13 :   g_bytes_unref (stdin_bytes);
    1756                 :            : }
    1757                 :            : 
    1758                 :            : static gboolean
    1759                 :         30 : communicate_result_validate_utf8 (const char            *stream_name,
    1760                 :            :                                   char                 **return_location,
    1761                 :            :                                   GMemoryOutputStream   *buffer,
    1762                 :            :                                   GError               **error)
    1763                 :            : {
    1764         [ -  + ]:         30 :   if (return_location == NULL)
    1765                 :          0 :     return TRUE;
    1766                 :            : 
    1767         [ +  + ]:         30 :   if (buffer)
    1768                 :            :     {
    1769                 :            :       const char *end;
    1770                 :         14 :       *return_location = g_memory_output_stream_steal_data (buffer);
    1771         [ +  + ]:         14 :       if (!g_utf8_validate (*return_location, -1, &end))
    1772                 :            :         {
    1773                 :          2 :           g_free (*return_location);
    1774                 :          2 :           *return_location = NULL;
    1775                 :          2 :           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
    1776                 :            :                        "Invalid UTF-8 in child %s at offset %lu",
    1777                 :            :                        stream_name,
    1778                 :          2 :                        (unsigned long) (end - *return_location));
    1779                 :          2 :           return FALSE;
    1780                 :            :         }
    1781                 :            :     }
    1782                 :            :   else
    1783                 :         16 :     *return_location = NULL;
    1784                 :            : 
    1785                 :         28 :   return TRUE;
    1786                 :            : }
    1787                 :            : 
    1788                 :            : /**
    1789                 :            :  * g_subprocess_communicate_utf8_finish:
    1790                 :            :  * @subprocess: Self
    1791                 :            :  * @result: Result
    1792                 :            :  * @stdout_buf: (out) (nullable) (optional) (transfer full): Return location for stdout data
    1793                 :            :  * @stderr_buf: (out) (nullable) (optional) (transfer full): Return location for stderr data
    1794                 :            :  * @error: Error
    1795                 :            :  *
    1796                 :            :  * Complete an invocation of g_subprocess_communicate_utf8_async().
    1797                 :            :  */
    1798                 :            : gboolean
    1799                 :         28 : g_subprocess_communicate_utf8_finish (GSubprocess   *subprocess,
    1800                 :            :                                       GAsyncResult  *result,
    1801                 :            :                                       char         **stdout_buf,
    1802                 :            :                                       char         **stderr_buf,
    1803                 :            :                                       GError       **error)
    1804                 :            : {
    1805                 :         28 :   gboolean ret = FALSE;
    1806                 :            :   CommunicateState *state;
    1807                 :         28 :   gchar *local_stdout_buf = NULL, *local_stderr_buf = NULL;
    1808                 :            : 
    1809                 :         28 :   g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
    1810                 :         28 :   g_return_val_if_fail (g_task_is_valid (result, subprocess), FALSE);
    1811                 :         28 :   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1812                 :            : 
    1813                 :         28 :   g_object_ref (result);
    1814                 :            : 
    1815                 :         28 :   state = g_task_get_task_data ((GTask*)result);
    1816         [ +  + ]:         28 :   if (!g_task_propagate_boolean ((GTask*)result, error))
    1817                 :         12 :     goto out;
    1818                 :            : 
    1819                 :            :   /* TODO - validate UTF-8 while streaming, rather than all at once.
    1820                 :            :    */
    1821         [ +  + ]:         16 :   if (!communicate_result_validate_utf8 ("stdout", &local_stdout_buf,
    1822                 :            :                                          state->stdout_buf,
    1823                 :            :                                          error))
    1824                 :          2 :     goto out;
    1825         [ -  + ]:         14 :   if (!communicate_result_validate_utf8 ("stderr", &local_stderr_buf,
    1826                 :            :                                          state->stderr_buf,
    1827                 :            :                                          error))
    1828                 :          0 :     goto out;
    1829                 :            : 
    1830                 :         14 :   ret = TRUE;
    1831                 :         28 :  out:
    1832                 :         28 :   g_object_unref (result);
    1833                 :            : 
    1834   [ +  +  +  - ]:         28 :   if (ret && stdout_buf != NULL)
    1835                 :         14 :     *stdout_buf = g_steal_pointer (&local_stdout_buf);
    1836   [ +  +  +  + ]:         28 :   if (ret && stderr_buf != NULL)
    1837                 :         12 :     *stderr_buf = g_steal_pointer (&local_stderr_buf);
    1838                 :            : 
    1839                 :         28 :   g_free (local_stderr_buf);
    1840                 :         28 :   g_free (local_stdout_buf);
    1841                 :            : 
    1842                 :         28 :   return ret;
    1843                 :            : }

Generated by: LCOV version 1.14