mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-11 11:56:16 +01:00
gspawn: Combine fork_exec() implementations
This is an internal change which won’t affect the public API. It should introduce no functional changes, but simplifies the code a little. The arguments from `fork_exec_with_pipes()` have been added to `fork_exec_with_fds()`. `child_close_fds` has been dropped since it’s now an implementation detail within the function. Signed-off-by: Philip Withnall <pwithnall@endlessos.org> Helps: #2097
This commit is contained in:
parent
63467c559e
commit
cddcd24b52
430
glib/gspawn.c
430
glib/gspawn.c
@ -167,46 +167,28 @@ static gint g_execute (const gchar *file,
|
||||
gchar *search_path_buffer,
|
||||
gsize search_path_buffer_len);
|
||||
|
||||
static gboolean fork_exec_with_pipes (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
gchar **argv,
|
||||
gchar **envp,
|
||||
gboolean close_descriptors,
|
||||
gboolean search_path,
|
||||
gboolean search_path_from_envp,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
gboolean child_inherits_stdin,
|
||||
gboolean file_and_argv_zero,
|
||||
gboolean cloexec_pipes,
|
||||
GSpawnChildSetupFunc child_setup,
|
||||
gpointer user_data,
|
||||
GPid *child_pid,
|
||||
gint *standard_input,
|
||||
gint *standard_output,
|
||||
gint *standard_error,
|
||||
GError **error);
|
||||
|
||||
static gboolean fork_exec_with_fds (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
gchar **argv,
|
||||
gchar **envp,
|
||||
gboolean close_descriptors,
|
||||
gboolean search_path,
|
||||
gboolean search_path_from_envp,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
gboolean child_inherits_stdin,
|
||||
gboolean file_and_argv_zero,
|
||||
gboolean cloexec_pipes,
|
||||
GSpawnChildSetupFunc child_setup,
|
||||
gpointer user_data,
|
||||
GPid *child_pid,
|
||||
gint *child_close_fds,
|
||||
gint stdin_fd,
|
||||
gint stdout_fd,
|
||||
gint stderr_fd,
|
||||
GError **error);
|
||||
static gboolean fork_exec (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
const gchar * const *argv,
|
||||
const gchar * const *envp,
|
||||
gboolean close_descriptors,
|
||||
gboolean search_path,
|
||||
gboolean search_path_from_envp,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
gboolean child_inherits_stdin,
|
||||
gboolean file_and_argv_zero,
|
||||
gboolean cloexec_pipes,
|
||||
GSpawnChildSetupFunc child_setup,
|
||||
gpointer user_data,
|
||||
GPid *child_pid,
|
||||
gint *stdin_pipe_out,
|
||||
gint *stdout_pipe_out,
|
||||
gint *stderr_pipe_out,
|
||||
gint stdin_fd,
|
||||
gint stdout_fd,
|
||||
gint stderr_fd,
|
||||
GError **error);
|
||||
|
||||
G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
|
||||
G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
|
||||
@ -264,6 +246,16 @@ g_spawn_async (const gchar *working_directory,
|
||||
error);
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gint
|
||||
steal_fd (gint *fd)
|
||||
{
|
||||
gint fd_out = *fd;
|
||||
*fd = -1;
|
||||
return fd_out;
|
||||
}
|
||||
|
||||
/* Avoids a danger in threaded situations (calling close()
|
||||
* on a file descriptor twice, and another thread has
|
||||
* re-opened it since the first close)
|
||||
@ -402,25 +394,26 @@ g_spawn_sync (const gchar *working_directory,
|
||||
if (standard_error)
|
||||
*standard_error = NULL;
|
||||
|
||||
if (!fork_exec_with_pipes (FALSE,
|
||||
working_directory,
|
||||
argv,
|
||||
envp,
|
||||
!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
|
||||
(flags & G_SPAWN_SEARCH_PATH) != 0,
|
||||
(flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
|
||||
(flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
|
||||
(flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
|
||||
(flags & G_SPAWN_CLOEXEC_PIPES) != 0,
|
||||
child_setup,
|
||||
user_data,
|
||||
&pid,
|
||||
NULL,
|
||||
standard_output ? &outpipe : NULL,
|
||||
standard_error ? &errpipe : NULL,
|
||||
error))
|
||||
if (!fork_exec (FALSE,
|
||||
working_directory,
|
||||
(const gchar * const *) argv,
|
||||
(const gchar * const *) envp,
|
||||
!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
|
||||
(flags & G_SPAWN_SEARCH_PATH) != 0,
|
||||
(flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
|
||||
(flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
|
||||
(flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
|
||||
(flags & G_SPAWN_CLOEXEC_PIPES) != 0,
|
||||
child_setup,
|
||||
user_data,
|
||||
&pid,
|
||||
NULL,
|
||||
standard_output ? &outpipe : NULL,
|
||||
standard_error ? &errpipe : NULL,
|
||||
-1, -1, -1,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* Read data from child. */
|
||||
@ -789,25 +782,26 @@ g_spawn_async_with_pipes (const gchar *working_directory,
|
||||
g_return_val_if_fail (standard_input == NULL ||
|
||||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
|
||||
|
||||
return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
|
||||
working_directory,
|
||||
argv,
|
||||
envp,
|
||||
!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
|
||||
(flags & G_SPAWN_SEARCH_PATH) != 0,
|
||||
(flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
|
||||
(flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
|
||||
(flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
|
||||
(flags & G_SPAWN_CLOEXEC_PIPES) != 0,
|
||||
child_setup,
|
||||
user_data,
|
||||
child_pid,
|
||||
standard_input,
|
||||
standard_output,
|
||||
standard_error,
|
||||
error);
|
||||
return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
|
||||
working_directory,
|
||||
(const gchar * const *) argv,
|
||||
(const gchar * const *) envp,
|
||||
!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
|
||||
(flags & G_SPAWN_SEARCH_PATH) != 0,
|
||||
(flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
|
||||
(flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
|
||||
(flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
|
||||
(flags & G_SPAWN_CLOEXEC_PIPES) != 0,
|
||||
child_setup,
|
||||
user_data,
|
||||
child_pid,
|
||||
standard_input,
|
||||
standard_output,
|
||||
standard_error,
|
||||
-1, -1, -1,
|
||||
error);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -869,26 +863,26 @@ g_spawn_async_with_fds (const gchar *working_directory,
|
||||
g_return_val_if_fail (stdin_fd < 0 ||
|
||||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
|
||||
|
||||
return fork_exec_with_fds (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
|
||||
working_directory,
|
||||
argv,
|
||||
envp,
|
||||
!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
|
||||
(flags & G_SPAWN_SEARCH_PATH) != 0,
|
||||
(flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
|
||||
(flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
|
||||
(flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
|
||||
(flags & G_SPAWN_CLOEXEC_PIPES) != 0,
|
||||
child_setup,
|
||||
user_data,
|
||||
child_pid,
|
||||
NULL,
|
||||
stdin_fd,
|
||||
stdout_fd,
|
||||
stderr_fd,
|
||||
error);
|
||||
return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
|
||||
working_directory,
|
||||
(const gchar * const *) argv,
|
||||
(const gchar * const *) envp,
|
||||
!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
|
||||
(flags & G_SPAWN_SEARCH_PATH) != 0,
|
||||
(flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
|
||||
(flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
|
||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
|
||||
(flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
|
||||
(flags & G_SPAWN_CLOEXEC_PIPES) != 0,
|
||||
child_setup,
|
||||
user_data,
|
||||
child_pid,
|
||||
NULL, NULL, NULL,
|
||||
stdin_fd,
|
||||
stdout_fd,
|
||||
stderr_fd,
|
||||
error);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1389,10 +1383,10 @@ do_exec (gint child_err_report_fd,
|
||||
gint stdout_fd,
|
||||
gint stderr_fd,
|
||||
const gchar *working_directory,
|
||||
gchar **argv,
|
||||
const gchar * const *argv,
|
||||
gchar **argv_buffer,
|
||||
gsize argv_buffer_len,
|
||||
gchar **envp,
|
||||
const gchar * const *envp,
|
||||
gboolean close_descriptors,
|
||||
const gchar *search_path,
|
||||
gchar *search_path_buffer,
|
||||
@ -1499,9 +1493,9 @@ do_exec (gint child_err_report_fd,
|
||||
}
|
||||
|
||||
g_execute (argv[0],
|
||||
file_and_argv_zero ? argv + 1 : argv,
|
||||
(gchar **) (file_and_argv_zero ? argv + 1 : argv),
|
||||
argv_buffer, argv_buffer_len,
|
||||
envp, search_path, search_path_buffer, search_path_buffer_len);
|
||||
(gchar **) envp, search_path, search_path_buffer, search_path_buffer_len);
|
||||
|
||||
/* Exec failed */
|
||||
write_err_and_exit (child_err_report_fd,
|
||||
@ -1559,8 +1553,8 @@ read_ints (int fd,
|
||||
|
||||
#ifdef POSIX_SPAWN_AVAILABLE
|
||||
static gboolean
|
||||
do_posix_spawn (gchar **argv,
|
||||
gchar **envp,
|
||||
do_posix_spawn (const gchar * const *argv,
|
||||
const gchar * const *envp,
|
||||
gboolean search_path,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
@ -1573,7 +1567,7 @@ do_posix_spawn (gchar **argv,
|
||||
gint stderr_fd)
|
||||
{
|
||||
pid_t pid;
|
||||
gchar **argv_pass;
|
||||
const gchar * const *argv_pass;
|
||||
posix_spawnattr_t attr;
|
||||
posix_spawn_file_actions_t file_actions;
|
||||
gint parent_close_fds[3];
|
||||
@ -1712,13 +1706,13 @@ do_posix_spawn (gchar **argv,
|
||||
|
||||
argv_pass = file_and_argv_zero ? argv + 1 : argv;
|
||||
if (envp == NULL)
|
||||
envp = environ;
|
||||
envp = (const gchar * const *) environ;
|
||||
|
||||
/* Don't search when it contains a slash. */
|
||||
if (!search_path || strchr (argv[0], '/') != NULL)
|
||||
r = posix_spawn (&pid, argv[0], &file_actions, &attr, argv_pass, envp);
|
||||
r = posix_spawn (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
|
||||
else
|
||||
r = posix_spawnp (&pid, argv[0], &file_actions, &attr, argv_pass, envp);
|
||||
r = posix_spawnp (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
|
||||
|
||||
if (r == 0 && child_pid != NULL)
|
||||
*child_pid = pid;
|
||||
@ -1737,26 +1731,28 @@ out_free_spawnattr:
|
||||
#endif /* POSIX_SPAWN_AVAILABLE */
|
||||
|
||||
static gboolean
|
||||
fork_exec_with_fds (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
gchar **argv,
|
||||
gchar **envp,
|
||||
gboolean close_descriptors,
|
||||
gboolean search_path,
|
||||
gboolean search_path_from_envp,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
gboolean child_inherits_stdin,
|
||||
gboolean file_and_argv_zero,
|
||||
gboolean cloexec_pipes,
|
||||
GSpawnChildSetupFunc child_setup,
|
||||
gpointer user_data,
|
||||
GPid *child_pid,
|
||||
gint *child_close_fds,
|
||||
gint stdin_fd,
|
||||
gint stdout_fd,
|
||||
gint stderr_fd,
|
||||
GError **error)
|
||||
fork_exec (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
const gchar * const *argv,
|
||||
const gchar * const *envp,
|
||||
gboolean close_descriptors,
|
||||
gboolean search_path,
|
||||
gboolean search_path_from_envp,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
gboolean child_inherits_stdin,
|
||||
gboolean file_and_argv_zero,
|
||||
gboolean cloexec_pipes,
|
||||
GSpawnChildSetupFunc child_setup,
|
||||
gpointer user_data,
|
||||
GPid *child_pid,
|
||||
gint *stdin_pipe_out,
|
||||
gint *stdout_pipe_out,
|
||||
gint *stderr_pipe_out,
|
||||
gint stdin_fd,
|
||||
gint stdout_fd,
|
||||
gint stderr_fd,
|
||||
GError **error)
|
||||
{
|
||||
GPid pid = -1;
|
||||
gint child_err_report_pipe[2] = { -1, -1 };
|
||||
@ -1770,6 +1766,42 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
gchar **argv_buffer = NULL;
|
||||
gchar **argv_buffer_heap = NULL;
|
||||
gsize argv_buffer_len = 0;
|
||||
gint stdin_pipe[2] = { -1, -1 };
|
||||
gint stdout_pipe[2] = { -1, -1 };
|
||||
gint stderr_pipe[2] = { -1, -1 };
|
||||
gint child_close_fds[4] = { -1, -1, -1, -1 };
|
||||
gint n_child_close_fds = 0;
|
||||
|
||||
g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
|
||||
g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
|
||||
g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
|
||||
|
||||
/* If pipes have been requested, open them */
|
||||
if (stdin_pipe_out != NULL)
|
||||
{
|
||||
if (!g_unix_open_pipe (stdin_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
child_close_fds[n_child_close_fds++] = stdin_pipe[1];
|
||||
stdin_fd = stdin_pipe[0];
|
||||
}
|
||||
|
||||
if (stdout_pipe_out != NULL)
|
||||
{
|
||||
if (!g_unix_open_pipe (stdout_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
child_close_fds[n_child_close_fds++] = stdout_pipe[0];
|
||||
stdout_fd = stdout_pipe[1];
|
||||
}
|
||||
|
||||
if (stderr_pipe_out != NULL)
|
||||
{
|
||||
if (!g_unix_open_pipe (stderr_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
child_close_fds[n_child_close_fds++] = stderr_pipe[0];
|
||||
stderr_fd = stderr_pipe[1];
|
||||
}
|
||||
|
||||
child_close_fds[n_child_close_fds++] = -1;
|
||||
|
||||
#ifdef POSIX_SPAWN_AVAILABLE
|
||||
if (!intermediate_child && working_directory == NULL && !close_descriptors &&
|
||||
@ -1792,7 +1824,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
stdout_fd,
|
||||
stderr_fd);
|
||||
if (status == 0)
|
||||
return TRUE;
|
||||
goto success;
|
||||
|
||||
if (status != ENOEXEC)
|
||||
{
|
||||
@ -1802,7 +1834,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
_("Failed to spawn child process “%s” (%s)"),
|
||||
argv[0],
|
||||
g_strerror (status));
|
||||
return FALSE;
|
||||
goto cleanup_and_fail;
|
||||
}
|
||||
|
||||
/* posix_spawn is not intended to support script execution. It does in
|
||||
@ -1829,7 +1861,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
* as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */
|
||||
chosen_search_path = NULL;
|
||||
if (search_path_from_envp)
|
||||
chosen_search_path = g_environ_getenv (envp, "PATH");
|
||||
chosen_search_path = g_environ_getenv ((gchar **) envp, "PATH");
|
||||
if (search_path && chosen_search_path == NULL)
|
||||
chosen_search_path = g_getenv ("PATH");
|
||||
|
||||
@ -1883,7 +1915,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
/* And allocate a buffer which is 2 elements longer than @argv, so that if
|
||||
* script_execute() has to be called later on, it can build a wrapper argv
|
||||
* array in this buffer. */
|
||||
argv_buffer_len = g_strv_length (argv) + 2;
|
||||
argv_buffer_len = g_strv_length ((gchar **) argv) + 2;
|
||||
if (argv_buffer_len < 4000 / sizeof (gchar *))
|
||||
{
|
||||
/* Prefer small stack allocations to avoid valgrind leak warnings
|
||||
@ -1897,11 +1929,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
}
|
||||
|
||||
if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error))
|
||||
{
|
||||
g_free (search_path_buffer_heap);
|
||||
g_free (argv_buffer_heap);
|
||||
return FALSE;
|
||||
}
|
||||
goto cleanup_and_fail;
|
||||
|
||||
if (intermediate_child && !g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
@ -1943,7 +1971,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
*/
|
||||
close_and_invalidate (&child_err_report_pipe[0]);
|
||||
close_and_invalidate (&child_pid_report_pipe[0]);
|
||||
if (child_close_fds != NULL)
|
||||
if (child_close_fds[0] != -1)
|
||||
{
|
||||
int i = -1;
|
||||
while (child_close_fds[++i] != -1)
|
||||
@ -2049,8 +2077,7 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
else if (errno == ECHILD)
|
||||
; /* do nothing, child already reaped */
|
||||
else
|
||||
g_warning ("waitpid() should not fail in "
|
||||
"'fork_exec_with_pipes'");
|
||||
g_warning ("waitpid() should not fail in 'fork_exec'");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2152,9 +2179,26 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
if (child_pid)
|
||||
*child_pid = pid;
|
||||
|
||||
return TRUE;
|
||||
goto success;
|
||||
}
|
||||
|
||||
success:
|
||||
/* Close the uncared-about ends of the pipes */
|
||||
close_and_invalidate (&stdin_pipe[0]);
|
||||
close_and_invalidate (&stdout_pipe[1]);
|
||||
close_and_invalidate (&stderr_pipe[1]);
|
||||
|
||||
if (stdin_pipe_out != NULL)
|
||||
*stdin_pipe_out = steal_fd (&stdin_pipe[1]);
|
||||
|
||||
if (stdout_pipe_out != NULL)
|
||||
*stdout_pipe_out = steal_fd (&stdout_pipe[0]);
|
||||
|
||||
if (stderr_pipe_out != NULL)
|
||||
*stderr_pipe_out = steal_fd (&stderr_pipe[0]);
|
||||
|
||||
return TRUE;
|
||||
|
||||
cleanup_and_fail:
|
||||
|
||||
/* There was an error from the Child, reap the child to avoid it being
|
||||
@ -2171,104 +2215,10 @@ fork_exec_with_fds (gboolean intermediate_child,
|
||||
else if (errno == ECHILD)
|
||||
; /* do nothing, child already reaped */
|
||||
else
|
||||
g_warning ("waitpid() should not fail in "
|
||||
"'fork_exec_with_pipes'");
|
||||
g_warning ("waitpid() should not fail in 'fork_exec'");
|
||||
}
|
||||
}
|
||||
|
||||
close_and_invalidate (&child_err_report_pipe[0]);
|
||||
close_and_invalidate (&child_err_report_pipe[1]);
|
||||
close_and_invalidate (&child_pid_report_pipe[0]);
|
||||
close_and_invalidate (&child_pid_report_pipe[1]);
|
||||
|
||||
g_free (search_path_buffer_heap);
|
||||
g_free (argv_buffer_heap);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fork_exec_with_pipes (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
gchar **argv,
|
||||
gchar **envp,
|
||||
gboolean close_descriptors,
|
||||
gboolean search_path,
|
||||
gboolean search_path_from_envp,
|
||||
gboolean stdout_to_null,
|
||||
gboolean stderr_to_null,
|
||||
gboolean child_inherits_stdin,
|
||||
gboolean file_and_argv_zero,
|
||||
gboolean cloexec_pipes,
|
||||
GSpawnChildSetupFunc child_setup,
|
||||
gpointer user_data,
|
||||
GPid *child_pid,
|
||||
gint *standard_input,
|
||||
gint *standard_output,
|
||||
gint *standard_error,
|
||||
GError **error)
|
||||
{
|
||||
guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0;
|
||||
gint stdin_pipe[2] = { -1, -1 };
|
||||
gint stdout_pipe[2] = { -1, -1 };
|
||||
gint stderr_pipe[2] = { -1, -1 };
|
||||
gint child_close_fds[4];
|
||||
gboolean ret;
|
||||
|
||||
if (standard_input && !g_unix_open_pipe (stdin_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
if (standard_output && !g_unix_open_pipe (stdout_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
if (standard_error && !g_unix_open_pipe (stderr_pipe, FD_CLOEXEC, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
child_close_fds[0] = stdin_pipe[1];
|
||||
child_close_fds[1] = stdout_pipe[0];
|
||||
child_close_fds[2] = stderr_pipe[0];
|
||||
child_close_fds[3] = -1;
|
||||
|
||||
ret = fork_exec_with_fds (intermediate_child,
|
||||
working_directory,
|
||||
argv,
|
||||
envp,
|
||||
close_descriptors,
|
||||
search_path,
|
||||
search_path_from_envp,
|
||||
stdout_to_null,
|
||||
stderr_to_null,
|
||||
child_inherits_stdin,
|
||||
file_and_argv_zero,
|
||||
pipe_flags,
|
||||
child_setup,
|
||||
user_data,
|
||||
child_pid,
|
||||
child_close_fds,
|
||||
stdin_pipe[0],
|
||||
stdout_pipe[1],
|
||||
stderr_pipe[1],
|
||||
error);
|
||||
if (!ret)
|
||||
goto cleanup_and_fail;
|
||||
|
||||
/* Close the uncared-about ends of the pipes */
|
||||
close_and_invalidate (&stdin_pipe[0]);
|
||||
close_and_invalidate (&stdout_pipe[1]);
|
||||
close_and_invalidate (&stderr_pipe[1]);
|
||||
|
||||
if (standard_input)
|
||||
*standard_input = stdin_pipe[1];
|
||||
|
||||
if (standard_output)
|
||||
*standard_output = stdout_pipe[0];
|
||||
|
||||
if (standard_error)
|
||||
*standard_error = stderr_pipe[0];
|
||||
|
||||
return TRUE;
|
||||
|
||||
cleanup_and_fail:
|
||||
close_and_invalidate (&stdin_pipe[0]);
|
||||
close_and_invalidate (&stdin_pipe[1]);
|
||||
close_and_invalidate (&stdout_pipe[0]);
|
||||
@ -2276,6 +2226,14 @@ cleanup_and_fail:
|
||||
close_and_invalidate (&stderr_pipe[0]);
|
||||
close_and_invalidate (&stderr_pipe[1]);
|
||||
|
||||
close_and_invalidate (&child_err_report_pipe[0]);
|
||||
close_and_invalidate (&child_err_report_pipe[1]);
|
||||
close_and_invalidate (&child_pid_report_pipe[0]);
|
||||
close_and_invalidate (&child_pid_report_pipe[1]);
|
||||
|
||||
g_clear_pointer (&search_path_buffer_heap, g_free);
|
||||
g_clear_pointer (&argv_buffer_heap, g_free);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user