mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-04 18:26:19 +01:00
gspawn: Use GUnixPipe on Unix
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
parent
9e20a7d0e7
commit
e80b0c4e4b
118
glib/gspawn.c
118
glib/gspawn.c
@ -2268,6 +2268,16 @@ out_free_spawnattr:
|
||||
}
|
||||
#endif /* POSIX_SPAWN_AVAILABLE */
|
||||
|
||||
static gboolean
|
||||
source_fds_collide_with_pipe (const GUnixPipe *pipefd,
|
||||
const int *source_fds,
|
||||
gsize n_fds,
|
||||
GError **error)
|
||||
{
|
||||
return (_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_READ], source_fds, n_fds, error) ||
|
||||
_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_WRITE], source_fds, n_fds, error));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fork_exec (gboolean intermediate_child,
|
||||
const gchar *working_directory,
|
||||
@ -2296,8 +2306,8 @@ fork_exec (gboolean intermediate_child,
|
||||
GError **error)
|
||||
{
|
||||
GPid pid = -1;
|
||||
gint child_err_report_pipe[2] = { -1, -1 };
|
||||
gint child_pid_report_pipe[2] = { -1, -1 };
|
||||
GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
|
||||
GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
|
||||
guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0;
|
||||
gint status;
|
||||
const gchar *chosen_search_path;
|
||||
@ -2307,9 +2317,9 @@ fork_exec (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 };
|
||||
GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
|
||||
GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
|
||||
GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
|
||||
gint child_close_fds[4] = { -1, -1, -1, -1 };
|
||||
gint n_child_close_fds = 0;
|
||||
gint *source_fds_copy = NULL;
|
||||
@ -2322,35 +2332,32 @@ fork_exec (gboolean intermediate_child,
|
||||
/* If pipes have been requested, open them */
|
||||
if (stdin_pipe_out != NULL)
|
||||
{
|
||||
if (!g_unix_open_pipe (stdin_pipe, pipe_flags, error))
|
||||
if (!g_unix_pipe_open (&stdin_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
if (_g_spawn_invalid_source_fd (stdin_pipe[0], source_fds, n_fds, error) ||
|
||||
_g_spawn_invalid_source_fd (stdin_pipe[1], source_fds, n_fds, error))
|
||||
if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
|
||||
goto cleanup_and_fail;
|
||||
child_close_fds[n_child_close_fds++] = stdin_pipe[1];
|
||||
stdin_fd = stdin_pipe[0];
|
||||
child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
|
||||
stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
|
||||
}
|
||||
|
||||
if (stdout_pipe_out != NULL)
|
||||
{
|
||||
if (!g_unix_open_pipe (stdout_pipe, pipe_flags, error))
|
||||
if (!g_unix_pipe_open (&stdout_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
if (_g_spawn_invalid_source_fd (stdout_pipe[0], source_fds, n_fds, error) ||
|
||||
_g_spawn_invalid_source_fd (stdout_pipe[1], source_fds, n_fds, error))
|
||||
if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
|
||||
goto cleanup_and_fail;
|
||||
child_close_fds[n_child_close_fds++] = stdout_pipe[0];
|
||||
stdout_fd = stdout_pipe[1];
|
||||
child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
|
||||
stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
|
||||
}
|
||||
|
||||
if (stderr_pipe_out != NULL)
|
||||
{
|
||||
if (!g_unix_open_pipe (stderr_pipe, pipe_flags, error))
|
||||
if (!g_unix_pipe_open (&stderr_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
if (_g_spawn_invalid_source_fd (stderr_pipe[0], source_fds, n_fds, error) ||
|
||||
_g_spawn_invalid_source_fd (stderr_pipe[1], source_fds, n_fds, error))
|
||||
if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, 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++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
|
||||
stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
|
||||
}
|
||||
|
||||
child_close_fds[n_child_close_fds++] = -1;
|
||||
@ -2488,18 +2495,16 @@ fork_exec (gboolean intermediate_child,
|
||||
if (n_fds > 0)
|
||||
memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
|
||||
|
||||
if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error))
|
||||
if (!g_unix_pipe_open (&child_err_report_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
if (_g_spawn_invalid_source_fd (child_err_report_pipe[0], source_fds, n_fds, error) ||
|
||||
_g_spawn_invalid_source_fd (child_err_report_pipe[1], source_fds, n_fds, error))
|
||||
if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
if (intermediate_child)
|
||||
{
|
||||
if (!g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error))
|
||||
if (!g_unix_pipe_open (&child_pid_report_pipe, pipe_flags, error))
|
||||
goto cleanup_and_fail;
|
||||
if (_g_spawn_invalid_source_fd (child_pid_report_pipe[0], source_fds, n_fds, error) ||
|
||||
_g_spawn_invalid_source_fd (child_pid_report_pipe[1], source_fds, n_fds, error))
|
||||
if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
|
||||
goto cleanup_and_fail;
|
||||
}
|
||||
|
||||
@ -2538,8 +2543,8 @@ fork_exec (gboolean intermediate_child,
|
||||
* not needed in the close_descriptors case,
|
||||
* though
|
||||
*/
|
||||
g_clear_fd (&child_err_report_pipe[0], NULL);
|
||||
g_clear_fd (&child_pid_report_pipe[0], NULL);
|
||||
g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||
if (child_close_fds[0] != -1)
|
||||
{
|
||||
int i = -1;
|
||||
@ -2561,16 +2566,16 @@ fork_exec (gboolean intermediate_child,
|
||||
if (grandchild_pid < 0)
|
||||
{
|
||||
/* report -1 as child PID */
|
||||
write_all (child_pid_report_pipe[1], &grandchild_pid,
|
||||
sizeof(grandchild_pid));
|
||||
write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||
&grandchild_pid, sizeof(grandchild_pid));
|
||||
|
||||
write_err_and_exit (child_err_report_pipe[1],
|
||||
write_err_and_exit (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||
CHILD_FORK_FAILED);
|
||||
}
|
||||
else if (grandchild_pid == 0)
|
||||
{
|
||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
||||
do_exec (child_err_report_pipe[1],
|
||||
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||
do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||
stdin_fd,
|
||||
stdout_fd,
|
||||
stderr_fd,
|
||||
@ -2595,8 +2600,9 @@ fork_exec (gboolean intermediate_child,
|
||||
}
|
||||
else
|
||||
{
|
||||
write_all (child_pid_report_pipe[1], &grandchild_pid, sizeof(grandchild_pid));
|
||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
||||
write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||
&grandchild_pid, sizeof(grandchild_pid));
|
||||
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||
|
||||
_exit (0);
|
||||
}
|
||||
@ -2606,7 +2612,7 @@ fork_exec (gboolean intermediate_child,
|
||||
/* Just run the child.
|
||||
*/
|
||||
|
||||
do_exec (child_err_report_pipe[1],
|
||||
do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||
stdin_fd,
|
||||
stdout_fd,
|
||||
stderr_fd,
|
||||
@ -2638,8 +2644,8 @@ fork_exec (gboolean intermediate_child,
|
||||
gint n_ints = 0;
|
||||
|
||||
/* Close the uncared-about ends of the pipes */
|
||||
g_clear_fd (&child_err_report_pipe[1], NULL);
|
||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
||||
g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||
|
||||
/* If we had an intermediate child, reap it */
|
||||
if (intermediate_child)
|
||||
@ -2657,7 +2663,7 @@ fork_exec (gboolean intermediate_child,
|
||||
}
|
||||
|
||||
|
||||
if (!read_ints (child_err_report_pipe[0],
|
||||
if (!read_ints (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_READ),
|
||||
buf, 2, &n_ints,
|
||||
error))
|
||||
goto cleanup_and_fail;
|
||||
@ -2738,7 +2744,7 @@ fork_exec (gboolean intermediate_child,
|
||||
{
|
||||
n_ints = 0;
|
||||
|
||||
if (!read_ints (child_pid_report_pipe[0],
|
||||
if (!read_ints (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_READ),
|
||||
buf, 1, &n_ints, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
@ -2761,8 +2767,8 @@ fork_exec (gboolean intermediate_child,
|
||||
}
|
||||
|
||||
/* Success against all odds! return the information */
|
||||
g_clear_fd (&child_err_report_pipe[0], NULL);
|
||||
g_clear_fd (&child_pid_report_pipe[0], NULL);
|
||||
g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||
|
||||
g_free (search_path_buffer_heap);
|
||||
g_free (argv_buffer_heap);
|
||||
@ -2776,18 +2782,18 @@ fork_exec (gboolean intermediate_child,
|
||||
|
||||
success:
|
||||
/* Close the uncared-about ends of the pipes */
|
||||
g_clear_fd (&stdin_pipe[0], NULL);
|
||||
g_clear_fd (&stdout_pipe[1], NULL);
|
||||
g_clear_fd (&stderr_pipe[1], NULL);
|
||||
g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||
g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||
g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||
|
||||
if (stdin_pipe_out != NULL)
|
||||
*stdin_pipe_out = g_steal_fd (&stdin_pipe[1]);
|
||||
*stdin_pipe_out = g_unix_pipe_steal (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
|
||||
|
||||
if (stdout_pipe_out != NULL)
|
||||
*stdout_pipe_out = g_steal_fd (&stdout_pipe[0]);
|
||||
*stdout_pipe_out = g_unix_pipe_steal (&stdout_pipe, G_UNIX_PIPE_END_READ);
|
||||
|
||||
if (stderr_pipe_out != NULL)
|
||||
*stderr_pipe_out = g_steal_fd (&stderr_pipe[0]);
|
||||
*stderr_pipe_out = g_unix_pipe_steal (&stderr_pipe, G_UNIX_PIPE_END_READ);
|
||||
|
||||
return TRUE;
|
||||
|
||||
@ -2811,17 +2817,11 @@ success:
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_fd (&stdin_pipe[0], NULL);
|
||||
g_clear_fd (&stdin_pipe[1], NULL);
|
||||
g_clear_fd (&stdout_pipe[0], NULL);
|
||||
g_clear_fd (&stdout_pipe[1], NULL);
|
||||
g_clear_fd (&stderr_pipe[0], NULL);
|
||||
g_clear_fd (&stderr_pipe[1], NULL);
|
||||
|
||||
g_clear_fd (&child_err_report_pipe[0], NULL);
|
||||
g_clear_fd (&child_err_report_pipe[1], NULL);
|
||||
g_clear_fd (&child_pid_report_pipe[0], NULL);
|
||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
||||
g_unix_pipe_clear (&stdin_pipe);
|
||||
g_unix_pipe_clear (&stdout_pipe);
|
||||
g_unix_pipe_clear (&stderr_pipe);
|
||||
g_unix_pipe_clear (&child_err_report_pipe);
|
||||
g_unix_pipe_clear (&child_pid_report_pipe);
|
||||
|
||||
g_clear_pointer (&search_path_buffer_heap, g_free);
|
||||
g_clear_pointer (&argv_buffer_heap, g_free);
|
||||
|
Loading…
Reference in New Issue
Block a user