gspawn-win32: Refactor internal spawn functions

This should introduce no functional changes, but condenses the variants
of the internal spawn implementation down to be more like `gspawn.c`.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #2097
This commit is contained in:
Philip Withnall 2021-02-15 13:34:26 +00:00
parent ba403908a2
commit a34b674134

View File

@ -531,19 +531,23 @@ do_spawn_directly (gint *exit_status,
} }
static gboolean static gboolean
do_spawn_with_fds (gint *exit_status, fork_exec (gint *exit_status,
gboolean do_return_handle, gboolean do_return_handle,
const gchar *working_directory, const gchar *working_directory,
gchar **argv, const gchar * const *argv,
char **envp, const gchar * const *envp,
GSpawnFlags flags, GSpawnFlags flags,
GSpawnChildSetupFunc child_setup, GSpawnChildSetupFunc child_setup,
GPid *child_pid, gpointer user_data,
gint stdin_fd, GPid *child_pid,
gint stdout_fd, gint *stdin_pipe_out,
gint stderr_fd, gint *stdout_pipe_out,
gint *err_report, gint *stderr_pipe_out,
GError **error) gint stdin_fd,
gint stdout_fd,
gint stderr_fd,
gint *err_report,
GError **error)
{ {
char **protected_argv; char **protected_argv;
char args[ARG_COUNT][10]; char args[ARG_COUNT][10];
@ -561,6 +565,13 @@ do_spawn_with_fds (gint *exit_status,
gchar *helper_process; gchar *helper_process;
wchar_t *whelper, **wargv, **wenvp; wchar_t *whelper, **wargv, **wenvp;
gchar *glib_dll_directory; gchar *glib_dll_directory;
int stdin_pipe[2] = { -1, -1 };
int stdout_pipe[2] = { -1, -1 };
int stderr_pipe[2] = { -1, -1 };
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 (child_setup && !warned_about_child_setup) if (child_setup && !warned_about_child_setup)
{ {
@ -568,6 +579,27 @@ do_spawn_with_fds (gint *exit_status,
g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored"); g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
} }
if (stdin_pipe_out != NULL)
{
if (!make_pipe (stdin_pipe, error))
goto cleanup_and_fail;
stdin_fd = stdin_pipe[0];
}
if (stdout_pipe_out != NULL)
{
if (!make_pipe (stdout_pipe, error))
goto cleanup_and_fail;
stdout_fd = stdout_pipe[1];
}
if (stderr_pipe_out != NULL)
{
if (!make_pipe (stderr_pipe, error))
goto cleanup_and_fail;
stderr_fd = stderr_pipe[1];
}
argc = protect_argv (argv, &protected_argv); argc = protect_argv (argv, &protected_argv);
if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 && if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 &&
@ -841,6 +873,20 @@ do_spawn_with_fds (gint *exit_status,
if (rc != -1) if (rc != -1)
CloseHandle ((HANDLE) rc); CloseHandle ((HANDLE) rc);
/* Close the other process's ends of the pipes in this process,
* otherwise the reader will never get EOF.
*/
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 = stdin_pipe[1];
if (stdout_pipe_out != NULL)
*stdout_pipe_out = stdout_pipe[0];
if (stderr_pipe_out != NULL)
*stderr_pipe_out = stderr_pipe[0];
return TRUE; return TRUE;
cleanup_and_fail: cleanup_and_fail:
@ -856,70 +902,6 @@ do_spawn_with_fds (gint *exit_status,
if (helper_sync_pipe[1] != -1) if (helper_sync_pipe[1] != -1)
close (helper_sync_pipe[1]); close (helper_sync_pipe[1]);
return FALSE;
}
static gboolean
do_spawn_with_pipes (gint *exit_status,
gboolean do_return_handle,
const gchar *working_directory,
gchar **argv,
char **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
GPid *child_pid,
gint *standard_input,
gint *standard_output,
gint *standard_error,
gint *err_report,
GError **error)
{
int stdin_pipe[2] = { -1, -1 };
int stdout_pipe[2] = { -1, -1 };
int stderr_pipe[2] = { -1, -1 };
if (standard_input && !make_pipe (stdin_pipe, error))
goto cleanup_and_fail;
if (standard_output && !make_pipe (stdout_pipe, error))
goto cleanup_and_fail;
if (standard_error && !make_pipe (stderr_pipe, error))
goto cleanup_and_fail;
if (!do_spawn_with_fds (exit_status,
do_return_handle,
working_directory,
argv,
envp,
flags,
child_setup,
child_pid,
stdin_pipe[0],
stdout_pipe[1],
stderr_pipe[1],
err_report,
error))
goto cleanup_and_fail;
/* Close the other process's ends of the pipes in this process,
* otherwise the reader will never get EOF.
*/
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:
if (stdin_pipe[0] != -1) if (stdin_pipe[0] != -1)
close (stdin_pipe[0]); close (stdin_pipe[0]);
if (stdin_pipe[1] != -1) if (stdin_pipe[1] != -1)
@ -980,19 +962,23 @@ g_spawn_sync (const gchar *working_directory,
if (standard_error) if (standard_error)
*standard_error = NULL; *standard_error = NULL;
if (!do_spawn_with_pipes (&status, if (!fork_exec (&status,
FALSE, FALSE,
working_directory, working_directory,
argv, (const gchar * const *) argv,
envp, (const gchar * const *) envp,
flags, flags,
child_setup, child_setup,
NULL, user_data,
NULL, NULL,
standard_output ? &outpipe : NULL, NULL,
standard_error ? &errpipe : NULL, standard_output ? &outpipe : NULL,
&reportpipe, standard_error ? &errpipe : NULL,
error)) -1,
-1,
-1,
&reportpipe,
error))
return FALSE; return FALSE;
/* Read data from child. */ /* Read data from child. */
@ -1200,19 +1186,23 @@ g_spawn_async_with_pipes (const gchar *working_directory,
g_return_val_if_fail (standard_input == NULL || g_return_val_if_fail (standard_input == NULL ||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE); !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
return do_spawn_with_pipes (NULL, return fork_exec (NULL,
(flags & G_SPAWN_DO_NOT_REAP_CHILD), (flags & G_SPAWN_DO_NOT_REAP_CHILD),
working_directory, working_directory,
argv, (const gchar * const *) argv,
envp, (const gchar * const *) envp,
flags, flags,
child_setup, child_setup,
child_pid, user_data,
standard_input, child_pid,
standard_output, standard_input,
standard_error, standard_output,
NULL, standard_error,
error); -1,
-1,
-1,
NULL,
error);
} }
gboolean gboolean
@ -1237,19 +1227,24 @@ g_spawn_async_with_fds (const gchar *working_directory,
g_return_val_if_fail (stdin_fd == -1 || g_return_val_if_fail (stdin_fd == -1 ||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE); !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
return do_spawn_with_fds (NULL, return fork_exec (NULL,
(flags & G_SPAWN_DO_NOT_REAP_CHILD), (flags & G_SPAWN_DO_NOT_REAP_CHILD),
working_directory, working_directory,
argv, (const gchar * const *) argv,
envp, (const gchar * const *) envp,
flags, flags,
child_setup, child_setup,
child_pid, user_data,
stdin_fd, child_pid,
stdout_fd, NULL,
stderr_fd, NULL,
NULL, NULL,
error); stdin_fd,
stdout_fd,
stderr_fd,
NULL,
error);
} }
gboolean gboolean