mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-10 12:55:48 +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 */
|
#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
|
static gboolean
|
||||||
fork_exec (gboolean intermediate_child,
|
fork_exec (gboolean intermediate_child,
|
||||||
const gchar *working_directory,
|
const gchar *working_directory,
|
||||||
@ -2296,8 +2306,8 @@ fork_exec (gboolean intermediate_child,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GPid pid = -1;
|
GPid pid = -1;
|
||||||
gint child_err_report_pipe[2] = { -1, -1 };
|
GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
|
||||||
gint child_pid_report_pipe[2] = { -1, -1 };
|
GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
|
||||||
guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0;
|
guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0;
|
||||||
gint status;
|
gint status;
|
||||||
const gchar *chosen_search_path;
|
const gchar *chosen_search_path;
|
||||||
@ -2307,9 +2317,9 @@ fork_exec (gboolean intermediate_child,
|
|||||||
gchar **argv_buffer = NULL;
|
gchar **argv_buffer = NULL;
|
||||||
gchar **argv_buffer_heap = NULL;
|
gchar **argv_buffer_heap = NULL;
|
||||||
gsize argv_buffer_len = 0;
|
gsize argv_buffer_len = 0;
|
||||||
gint stdin_pipe[2] = { -1, -1 };
|
GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
|
||||||
gint stdout_pipe[2] = { -1, -1 };
|
GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
|
||||||
gint stderr_pipe[2] = { -1, -1 };
|
GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
|
||||||
gint child_close_fds[4] = { -1, -1, -1, -1 };
|
gint child_close_fds[4] = { -1, -1, -1, -1 };
|
||||||
gint n_child_close_fds = 0;
|
gint n_child_close_fds = 0;
|
||||||
gint *source_fds_copy = NULL;
|
gint *source_fds_copy = NULL;
|
||||||
@ -2322,35 +2332,32 @@ fork_exec (gboolean intermediate_child,
|
|||||||
/* If pipes have been requested, open them */
|
/* If pipes have been requested, open them */
|
||||||
if (stdin_pipe_out != NULL)
|
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;
|
goto cleanup_and_fail;
|
||||||
if (_g_spawn_invalid_source_fd (stdin_pipe[0], source_fds, n_fds, error) ||
|
if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
|
||||||
_g_spawn_invalid_source_fd (stdin_pipe[1], source_fds, n_fds, error))
|
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
child_close_fds[n_child_close_fds++] = stdin_pipe[1];
|
child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
|
||||||
stdin_fd = stdin_pipe[0];
|
stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdout_pipe_out != NULL)
|
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;
|
goto cleanup_and_fail;
|
||||||
if (_g_spawn_invalid_source_fd (stdout_pipe[0], source_fds, n_fds, error) ||
|
if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
|
||||||
_g_spawn_invalid_source_fd (stdout_pipe[1], source_fds, n_fds, error))
|
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
child_close_fds[n_child_close_fds++] = stdout_pipe[0];
|
child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
|
||||||
stdout_fd = stdout_pipe[1];
|
stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stderr_pipe_out != NULL)
|
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;
|
goto cleanup_and_fail;
|
||||||
if (_g_spawn_invalid_source_fd (stderr_pipe[0], source_fds, n_fds, error) ||
|
if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, error))
|
||||||
_g_spawn_invalid_source_fd (stderr_pipe[1], source_fds, n_fds, error))
|
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
child_close_fds[n_child_close_fds++] = stderr_pipe[0];
|
child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
|
||||||
stderr_fd = stderr_pipe[1];
|
stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
child_close_fds[n_child_close_fds++] = -1;
|
child_close_fds[n_child_close_fds++] = -1;
|
||||||
@ -2488,18 +2495,16 @@ fork_exec (gboolean intermediate_child,
|
|||||||
if (n_fds > 0)
|
if (n_fds > 0)
|
||||||
memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
|
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;
|
goto cleanup_and_fail;
|
||||||
if (_g_spawn_invalid_source_fd (child_err_report_pipe[0], source_fds, n_fds, error) ||
|
if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
|
||||||
_g_spawn_invalid_source_fd (child_err_report_pipe[1], source_fds, n_fds, error))
|
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
|
|
||||||
if (intermediate_child)
|
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;
|
goto cleanup_and_fail;
|
||||||
if (_g_spawn_invalid_source_fd (child_pid_report_pipe[0], source_fds, n_fds, error) ||
|
if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
|
||||||
_g_spawn_invalid_source_fd (child_pid_report_pipe[1], source_fds, n_fds, error))
|
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2538,8 +2543,8 @@ fork_exec (gboolean intermediate_child,
|
|||||||
* not needed in the close_descriptors case,
|
* not needed in the close_descriptors case,
|
||||||
* though
|
* though
|
||||||
*/
|
*/
|
||||||
g_clear_fd (&child_err_report_pipe[0], NULL);
|
g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||||
g_clear_fd (&child_pid_report_pipe[0], NULL);
|
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||||
if (child_close_fds[0] != -1)
|
if (child_close_fds[0] != -1)
|
||||||
{
|
{
|
||||||
int i = -1;
|
int i = -1;
|
||||||
@ -2561,16 +2566,16 @@ fork_exec (gboolean intermediate_child,
|
|||||||
if (grandchild_pid < 0)
|
if (grandchild_pid < 0)
|
||||||
{
|
{
|
||||||
/* report -1 as child PID */
|
/* report -1 as child PID */
|
||||||
write_all (child_pid_report_pipe[1], &grandchild_pid,
|
write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||||
sizeof(grandchild_pid));
|
&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);
|
CHILD_FORK_FAILED);
|
||||||
}
|
}
|
||||||
else if (grandchild_pid == 0)
|
else if (grandchild_pid == 0)
|
||||||
{
|
{
|
||||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||||
do_exec (child_err_report_pipe[1],
|
do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
|
||||||
stdin_fd,
|
stdin_fd,
|
||||||
stdout_fd,
|
stdout_fd,
|
||||||
stderr_fd,
|
stderr_fd,
|
||||||
@ -2595,8 +2600,9 @@ fork_exec (gboolean intermediate_child,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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),
|
||||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
&grandchild_pid, sizeof(grandchild_pid));
|
||||||
|
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||||
|
|
||||||
_exit (0);
|
_exit (0);
|
||||||
}
|
}
|
||||||
@ -2606,7 +2612,7 @@ fork_exec (gboolean intermediate_child,
|
|||||||
/* Just run the 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,
|
stdin_fd,
|
||||||
stdout_fd,
|
stdout_fd,
|
||||||
stderr_fd,
|
stderr_fd,
|
||||||
@ -2638,8 +2644,8 @@ fork_exec (gboolean intermediate_child,
|
|||||||
gint n_ints = 0;
|
gint n_ints = 0;
|
||||||
|
|
||||||
/* Close the uncared-about ends of the pipes */
|
/* Close the uncared-about ends of the pipes */
|
||||||
g_clear_fd (&child_err_report_pipe[1], NULL);
|
g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||||
g_clear_fd (&child_pid_report_pipe[1], NULL);
|
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||||
|
|
||||||
/* If we had an intermediate child, reap it */
|
/* If we had an intermediate child, reap it */
|
||||||
if (intermediate_child)
|
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,
|
buf, 2, &n_ints,
|
||||||
error))
|
error))
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
@ -2738,7 +2744,7 @@ fork_exec (gboolean intermediate_child,
|
|||||||
{
|
{
|
||||||
n_ints = 0;
|
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))
|
buf, 1, &n_ints, error))
|
||||||
goto cleanup_and_fail;
|
goto cleanup_and_fail;
|
||||||
|
|
||||||
@ -2761,8 +2767,8 @@ fork_exec (gboolean intermediate_child,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Success against all odds! return the information */
|
/* Success against all odds! return the information */
|
||||||
g_clear_fd (&child_err_report_pipe[0], NULL);
|
g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||||
g_clear_fd (&child_pid_report_pipe[0], NULL);
|
g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||||
|
|
||||||
g_free (search_path_buffer_heap);
|
g_free (search_path_buffer_heap);
|
||||||
g_free (argv_buffer_heap);
|
g_free (argv_buffer_heap);
|
||||||
@ -2776,18 +2782,18 @@ fork_exec (gboolean intermediate_child,
|
|||||||
|
|
||||||
success:
|
success:
|
||||||
/* Close the uncared-about ends of the pipes */
|
/* Close the uncared-about ends of the pipes */
|
||||||
g_clear_fd (&stdin_pipe[0], NULL);
|
g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
|
||||||
g_clear_fd (&stdout_pipe[1], NULL);
|
g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||||
g_clear_fd (&stderr_pipe[1], NULL);
|
g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
|
||||||
|
|
||||||
if (stdin_pipe_out != 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)
|
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)
|
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;
|
return TRUE;
|
||||||
|
|
||||||
@ -2811,17 +2817,11 @@ success:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_fd (&stdin_pipe[0], NULL);
|
g_unix_pipe_clear (&stdin_pipe);
|
||||||
g_clear_fd (&stdin_pipe[1], NULL);
|
g_unix_pipe_clear (&stdout_pipe);
|
||||||
g_clear_fd (&stdout_pipe[0], NULL);
|
g_unix_pipe_clear (&stderr_pipe);
|
||||||
g_clear_fd (&stdout_pipe[1], NULL);
|
g_unix_pipe_clear (&child_err_report_pipe);
|
||||||
g_clear_fd (&stderr_pipe[0], NULL);
|
g_unix_pipe_clear (&child_pid_report_pipe);
|
||||||
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_clear_pointer (&search_path_buffer_heap, g_free);
|
g_clear_pointer (&search_path_buffer_heap, g_free);
|
||||||
g_clear_pointer (&argv_buffer_heap, g_free);
|
g_clear_pointer (&argv_buffer_heap, g_free);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user