mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-28 23:16:14 +01:00
Add g_spawn_check_exit_status()
Many (if not "almost all") programs that spawn other programs via g_spawn_sync() or the like simply want to check whether or not the child exited successfully, but doing so requires use of platform-specific functionality and there's actually a fair amount of boilerplate involved. This new API will help drain a *lot* of mostly duplicated code in GNOME, from gnome-session to gdm. And we can see that some bits even inside GLib were doing it wrong; for example checking the exit status on Unix, but ignoring it on Windows. https://bugzilla.gnome.org/show_bug.cgi?id=679691
This commit is contained in:
parent
82d914d808
commit
f7abd3ce13
@ -1093,6 +1093,7 @@ GSpawnChildSetupFunc
|
|||||||
g_spawn_async_with_pipes
|
g_spawn_async_with_pipes
|
||||||
g_spawn_async
|
g_spawn_async
|
||||||
g_spawn_sync
|
g_spawn_sync
|
||||||
|
g_spawn_check_exit_status
|
||||||
g_spawn_command_line_async
|
g_spawn_command_line_async
|
||||||
g_spawn_command_line_sync
|
g_spawn_command_line_sync
|
||||||
g_spawn_close_pid
|
g_spawn_close_pid
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
|
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
#include <gio/gunixsocketaddress.h>
|
#include <gio/gunixsocketaddress.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
@ -1062,40 +1061,16 @@ get_session_address_dbus_launch (GError **error)
|
|||||||
&launch_stderr,
|
&launch_stderr,
|
||||||
&exit_status,
|
&exit_status,
|
||||||
error))
|
error))
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_spawn_check_exit_status (exit_status, error))
|
||||||
{
|
{
|
||||||
g_prefix_error (error, _("Error spawning command line `%s': "), command_line);
|
g_prefix_error (error, _("Error spawning command line `%s': "), command_line);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WIFEXITED (exit_status))
|
|
||||||
{
|
|
||||||
gchar *escaped_stderr;
|
|
||||||
escaped_stderr = g_strescape (launch_stderr, "");
|
|
||||||
g_set_error (error,
|
|
||||||
G_IO_ERROR,
|
|
||||||
G_IO_ERROR_FAILED,
|
|
||||||
_("Abnormal program termination spawning command line `%s': %s"),
|
|
||||||
command_line,
|
|
||||||
escaped_stderr);
|
|
||||||
g_free (escaped_stderr);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WEXITSTATUS (exit_status) != 0)
|
|
||||||
{
|
|
||||||
gchar *escaped_stderr;
|
|
||||||
escaped_stderr = g_strescape (launch_stderr, "");
|
|
||||||
g_set_error (error,
|
|
||||||
G_IO_ERROR,
|
|
||||||
G_IO_ERROR_FAILED,
|
|
||||||
_("Command line `%s' exited with non-zero exit status %d: %s"),
|
|
||||||
command_line,
|
|
||||||
WEXITSTATUS (exit_status),
|
|
||||||
escaped_stderr);
|
|
||||||
g_free (escaped_stderr);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* From the dbus-launch(1) man page:
|
/* From the dbus-launch(1) man page:
|
||||||
*
|
*
|
||||||
* --binary-syntax Write to stdout a nul-terminated bus address,
|
* --binary-syntax Write to stdout a nul-terminated bus address,
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CRT_EXTERNS_H
|
#ifdef HAVE_CRT_EXTERNS_H
|
||||||
#include <crt_externs.h>
|
#include <crt_externs.h>
|
||||||
@ -1850,8 +1849,7 @@ update_program_done (GPid pid,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
/* Did the application exit correctly */
|
/* Did the application exit correctly */
|
||||||
if (WIFEXITED (status) &&
|
if (g_spawn_check_exit_status (status, NULL))
|
||||||
WEXITSTATUS (status) == 0)
|
|
||||||
{
|
{
|
||||||
/* Here we could clean out any caches in use */
|
/* Here we could clean out any caches in use */
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,6 @@
|
|||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gio/gmemoryoutputstream.h>
|
#include <gio/gmemoryoutputstream.h>
|
||||||
#include <gio/gzlibcompressor.h>
|
#include <gio/gzlibcompressor.h>
|
||||||
@ -331,14 +328,14 @@ end_element (GMarkupParseContext *context,
|
|||||||
g_propagate_error (error, my_error);
|
g_propagate_error (error, my_error);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
|
||||||
if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
|
/* Ugly...we shoud probably just let stderr be inherited */
|
||||||
|
if (!g_spawn_check_exit_status (status, NULL))
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
_("Error processing input file with xmllint:\n%s"), stderr_child);
|
_("Error processing input file with xmllint:\n%s"), stderr_child);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
g_free (stderr_child);
|
g_free (stderr_child);
|
||||||
g_free (real_file);
|
g_free (real_file);
|
||||||
@ -387,14 +384,13 @@ end_element (GMarkupParseContext *context,
|
|||||||
g_propagate_error (error, my_error);
|
g_propagate_error (error, my_error);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
|
||||||
if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
|
if (!g_spawn_check_exit_status (status, NULL))
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
_("Error processing input file with to-pixdata:\n%s"), stderr_child);
|
_("Error processing input file with to-pixdata:\n%s"), stderr_child);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
g_free (stderr_child);
|
g_free (stderr_child);
|
||||||
g_free (real_file);
|
g_free (real_file);
|
||||||
|
@ -25,9 +25,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gdbus-tests.h"
|
#include "gdbus-tests.h"
|
||||||
|
|
||||||
@ -97,10 +94,8 @@ test_connection_flush (void)
|
|||||||
&exit_status,
|
&exit_status,
|
||||||
&error);
|
&error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
g_spawn_check_exit_status (exit_status, &error);
|
||||||
g_assert (WIFEXITED (exit_status));
|
g_assert_no_error (error);
|
||||||
g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
|
|
||||||
#endif
|
|
||||||
g_assert (ret);
|
g_assert (ret);
|
||||||
|
|
||||||
timeout_mainloop_id = g_timeout_add (1000, test_connection_flush_on_timeout, GUINT_TO_POINTER (n));
|
timeout_mainloop_id = g_timeout_add (1000, test_connection_flush_on_timeout, GUINT_TO_POINTER (n));
|
||||||
|
@ -141,7 +141,7 @@ test_connection_life_cycle (void)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
_g_assert_error_domain (error, G_IO_ERROR);
|
g_assert (error != NULL);
|
||||||
g_assert (!g_dbus_error_is_remote_error (error));
|
g_assert (!g_dbus_error_is_remote_error (error));
|
||||||
g_assert (c == NULL);
|
g_assert (c == NULL);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
|
@ -980,6 +980,7 @@ g_spawn_command_line_async PRIVATE
|
|||||||
g_spawn_command_line_sync PRIVATE
|
g_spawn_command_line_sync PRIVATE
|
||||||
#endif
|
#endif
|
||||||
g_spawn_error_quark
|
g_spawn_error_quark
|
||||||
|
g_spawn_exit_error_quark
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
g_spawn_sync PRIVATE
|
g_spawn_sync PRIVATE
|
||||||
#endif
|
#endif
|
||||||
@ -990,6 +991,7 @@ g_spawn_command_line_async_utf8
|
|||||||
g_spawn_command_line_sync_utf8
|
g_spawn_command_line_sync_utf8
|
||||||
g_spawn_sync_utf8
|
g_spawn_sync_utf8
|
||||||
#endif
|
#endif
|
||||||
|
g_spawn_check_exit_status
|
||||||
#if !defined(G_OS_UNIX) || defined(G_STDIO_NO_WRAP_ON_UNIX)
|
#if !defined(G_OS_UNIX) || defined(G_STDIO_NO_WRAP_ON_UNIX)
|
||||||
/* gstdio wrappers */
|
/* gstdio wrappers */
|
||||||
g_chmod
|
g_chmod
|
||||||
|
12
glib/gmain.c
12
glib/gmain.c
@ -4665,10 +4665,14 @@ g_child_watch_source_new (GPid pid)
|
|||||||
* you will need to pass #G_SPAWN_DO_NOT_REAP_CHILD as flag to
|
* you will need to pass #G_SPAWN_DO_NOT_REAP_CHILD as flag to
|
||||||
* the spawn function for the child watching to work.
|
* the spawn function for the child watching to work.
|
||||||
*
|
*
|
||||||
* Note that on platforms where #GPid must be explicitly closed
|
* In many programs, you will want to call g_spawn_check_exit_status()
|
||||||
* (see g_spawn_close_pid()) @pid must not be closed while the
|
* in the callback to determine whether or not the child exited
|
||||||
* source is still active. Typically, you will want to call
|
* successfully.
|
||||||
* g_spawn_close_pid() in the callback function for the source.
|
*
|
||||||
|
* Also, note that on platforms where #GPid must be explicitly closed
|
||||||
|
* (see g_spawn_close_pid()) @pid must not be closed while the source
|
||||||
|
* is still active. Typically, you should invoke g_spawn_close_pid()
|
||||||
|
* in the callback function for the source.
|
||||||
*
|
*
|
||||||
* GLib supports only a single callback per process id.
|
* GLib supports only a single callback per process id.
|
||||||
*
|
*
|
||||||
|
@ -139,11 +139,13 @@ typedef gboolean (*GSourceFunc) (gpointer user_data);
|
|||||||
/**
|
/**
|
||||||
* GChildWatchFunc:
|
* GChildWatchFunc:
|
||||||
* @pid: the process id of the child process
|
* @pid: the process id of the child process
|
||||||
* @status: Status information about the child process,
|
* @status: Status information about the child process, encoded
|
||||||
* see waitpid(2) for more information about this field
|
* in a platform-specific manner
|
||||||
* @user_data: user data passed to g_child_watch_add()
|
* @user_data: user data passed to g_child_watch_add()
|
||||||
*
|
*
|
||||||
* The type of functions to be called when a child exists.
|
* Prototype of a #GChildWatchSource callback, called when a child
|
||||||
|
* process has exited. To interpret @status, see the documentation
|
||||||
|
* for g_spawn_check_exit_status().
|
||||||
*/
|
*/
|
||||||
typedef void (*GChildWatchFunc) (GPid pid,
|
typedef void (*GChildWatchFunc) (GPid pid,
|
||||||
gint status,
|
gint status,
|
||||||
|
124
glib/gspawn.c
124
glib/gspawn.c
@ -94,6 +94,12 @@ g_spawn_error_quark (void)
|
|||||||
return g_quark_from_static_string ("g-exec-error-quark");
|
return g_quark_from_static_string ("g-exec-error-quark");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
g_spawn_exit_error_quark (void)
|
||||||
|
{
|
||||||
|
return g_quark_from_static_string ("g-spawn-exit-error-quark");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_spawn_async:
|
* g_spawn_async:
|
||||||
* @working_directory: (allow-none): child's current working directory, or %NULL to inherit parent's
|
* @working_directory: (allow-none): child's current working directory, or %NULL to inherit parent's
|
||||||
@ -232,11 +238,13 @@ read_data (GString *str,
|
|||||||
* if those parameters are non-%NULL. Note that you must set the
|
* if those parameters are non-%NULL. Note that you must set the
|
||||||
* %G_SPAWN_STDOUT_TO_DEV_NULL and %G_SPAWN_STDERR_TO_DEV_NULL flags when
|
* %G_SPAWN_STDOUT_TO_DEV_NULL and %G_SPAWN_STDERR_TO_DEV_NULL flags when
|
||||||
* passing %NULL for @standard_output and @standard_error.
|
* passing %NULL for @standard_output and @standard_error.
|
||||||
* If @exit_status is non-%NULL, the exit status of the child is stored
|
*
|
||||||
* there as it would be returned by waitpid(); standard UNIX macros such
|
* If @exit_status is non-%NULL, the platform-specific exit status of
|
||||||
* as WIFEXITED() and WEXITSTATUS() must be used to evaluate the exit status.
|
* the child is stored there; see the doucumentation of
|
||||||
* Note that this function call waitpid() even if @exit_status is %NULL, and
|
* g_spawn_check_exit_status() for how to use and interpret this.
|
||||||
* does not accept the %G_SPAWN_DO_NOT_REAP_CHILD flag.
|
* Note that it is invalid to pass %G_SPAWN_DO_NOT_REAP_CHILD in
|
||||||
|
* @flags.
|
||||||
|
*
|
||||||
* If an error occurs, no data is returned in @standard_output,
|
* If an error occurs, no data is returned in @standard_output,
|
||||||
* @standard_error, or @exit_status.
|
* @standard_error, or @exit_status.
|
||||||
*
|
*
|
||||||
@ -701,9 +709,9 @@ g_spawn_async_with_pipes (const gchar *working_directory,
|
|||||||
* appropriate. Possible errors are those from g_spawn_sync() and those
|
* appropriate. Possible errors are those from g_spawn_sync() and those
|
||||||
* from g_shell_parse_argv().
|
* from g_shell_parse_argv().
|
||||||
*
|
*
|
||||||
* If @exit_status is non-%NULL, the exit status of the child is stored there as
|
* If @exit_status is non-%NULL, the platform-specific exit status of
|
||||||
* it would be returned by waitpid(); standard UNIX macros such as WIFEXITED()
|
* the child is stored there; see the documentation of
|
||||||
* and WEXITSTATUS() must be used to evaluate the exit status.
|
* g_spawn_check_exit_status() for how to use and interpret this.
|
||||||
*
|
*
|
||||||
* On Windows, please note the implications of g_shell_parse_argv()
|
* On Windows, please note the implications of g_shell_parse_argv()
|
||||||
* parsing @command_line. Parsing is done according to Unix shell rules, not
|
* parsing @command_line. Parsing is done according to Unix shell rules, not
|
||||||
@ -793,6 +801,106 @@ g_spawn_command_line_async (const gchar *command_line,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_spawn_check_exit_status:
|
||||||
|
* @exit_status: An exit code as returned from g_spawn_sync()
|
||||||
|
* @error: a #GError
|
||||||
|
*
|
||||||
|
* Set @error if @exit_status indicates the child exited abnormally
|
||||||
|
* (e.g. with a nonzero exit code, or via a fatal signal).
|
||||||
|
*
|
||||||
|
* The g_spawn_sync() and g_child_watch_add() family of APIs return an
|
||||||
|
* exit status for subprocesses encoded in a platform-specific way.
|
||||||
|
* On Unix, this is guaranteed to be in the same format
|
||||||
|
* <literal>waitpid(2)</literal> returns, and on Windows it is
|
||||||
|
* guaranteed to be the result of
|
||||||
|
* <literal>GetExitCodeProcess()</literal>. Prior to the introduction
|
||||||
|
* of this function in GLib 2.34, interpreting @exit_status required
|
||||||
|
* use of platform-specific APIs, which is problematic for software
|
||||||
|
* using GLib as a cross-platform layer.
|
||||||
|
*
|
||||||
|
* Additionally, many programs simply want to determine whether or not
|
||||||
|
* the child exited successfully, and either propagate a #GError or
|
||||||
|
* print a message to standard error. In that common case, this
|
||||||
|
* function can be used. Note that the error message in @error will
|
||||||
|
* contain human-readable information about the exit status.
|
||||||
|
*
|
||||||
|
* The <literal>domain</literal> and <literal>code</literal> of @error
|
||||||
|
* have special semantics in the case where the process has an "exit
|
||||||
|
* code", as opposed to being killed by a signal. On Unix, this
|
||||||
|
* happens if <literal>WIFEXITED</literal> would be true of
|
||||||
|
* @exit_status. On Windows, it is always the case.
|
||||||
|
*
|
||||||
|
* The special semantics are that the actual exit code will be the
|
||||||
|
* code set in @error, and the domain will be %G_SPAWN_EXIT_ERROR.
|
||||||
|
* This allows you to differentiate between different exit codes.
|
||||||
|
*
|
||||||
|
* If the process was terminated by some means other than an exit
|
||||||
|
* status, the domain will be %G_SPAWN_ERROR, and the code will be
|
||||||
|
* %G_SPAWN_ERROR_FAILED.
|
||||||
|
*
|
||||||
|
* This function just offers convenience; you can of course also check
|
||||||
|
* the available platform via a macro such as %G_OS_UNIX, and use
|
||||||
|
* <literal>WIFEXITED()</literal> and <literal>WEXITSTATUS()</literal>
|
||||||
|
* on @exit_status directly. Do not attempt to scan or parse the
|
||||||
|
* error message string; it may be translated and/or change in future
|
||||||
|
* versions of GLib.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if child exited successfully, %FALSE otherwise (and @error will be set)
|
||||||
|
* Since: 2.34
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
g_spawn_check_exit_status (gint exit_status,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
if (WIFEXITED (exit_status))
|
||||||
|
{
|
||||||
|
if (WEXITSTATUS (exit_status) != 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (exit_status),
|
||||||
|
_("Child process exited with code %ld"),
|
||||||
|
(long) WEXITSTATUS (exit_status));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (WIFSIGNALED (exit_status))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
||||||
|
_("Child process killed by signal %ld"),
|
||||||
|
(long) WTERMSIG (exit_status));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else if (WIFSTOPPED (exit_status))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
||||||
|
_("Child process stopped by signal %ld"),
|
||||||
|
(long) WSTOPSIG (exit_status));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
||||||
|
_("Child process exited abnormally"));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (exit_status != 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_EXIT_ERROR, exit_status,
|
||||||
|
_("Child process exited with code %ld"),
|
||||||
|
(long) exit_status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
exec_err_to_g_error (gint en)
|
exec_err_to_g_error (gint en)
|
||||||
{
|
{
|
||||||
|
@ -96,6 +96,14 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
} GSpawnError;
|
} GSpawnError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_SPAWN_EXIT_ERROR:
|
||||||
|
*
|
||||||
|
* Error domain used by g_spawn_check_exit_status(). The code
|
||||||
|
* will be the the program exit code.
|
||||||
|
*/
|
||||||
|
#define G_SPAWN_EXIT_ERROR g_spawn_exit_error_quark ()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GSpawnChildSetupFunc:
|
* GSpawnChildSetupFunc:
|
||||||
* @user_data: user data to pass to the function.
|
* @user_data: user data to pass to the function.
|
||||||
@ -176,6 +184,7 @@ typedef enum
|
|||||||
} GSpawnFlags;
|
} GSpawnFlags;
|
||||||
|
|
||||||
GQuark g_spawn_error_quark (void);
|
GQuark g_spawn_error_quark (void);
|
||||||
|
GQuark g_spawn_exit_error_quark (void);
|
||||||
|
|
||||||
#ifndef __GTK_DOC_IGNORE__
|
#ifndef __GTK_DOC_IGNORE__
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
@ -236,6 +245,10 @@ gboolean g_spawn_command_line_sync (const gchar *command_line,
|
|||||||
gboolean g_spawn_command_line_async (const gchar *command_line,
|
gboolean g_spawn_command_line_async (const gchar *command_line,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_34
|
||||||
|
gboolean g_spawn_check_exit_status (gint exit_status,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
void g_spawn_close_pid (GPid pid);
|
void g_spawn_close_pid (GPid pid);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
Loading…
Reference in New Issue
Block a user