diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-29 10:32:31 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-29 10:32:31 +0900 |
commit | dede7e78ca86551aa696e2b3c7bf14f242c103d8 (patch) | |
tree | 3fb0344ba8903b949ea9dc81ad6b1f2b93d6c49a /gio/gsubprocess.c | |
parent | c5080b2dbc1053bdacc0ca59022fb1a9793895c5 (diff) | |
download | glib-dede7e78ca86551aa696e2b3c7bf14f242c103d8.tar.gz glib-dede7e78ca86551aa696e2b3c7bf14f242c103d8.tar.bz2 glib-dede7e78ca86551aa696e2b3c7bf14f242c103d8.zip |
Imported Upstream version 2.67.4upstream/2.67.4
Diffstat (limited to 'gio/gsubprocess.c')
-rw-r--r-- | gio/gsubprocess.c | 220 |
1 files changed, 30 insertions, 190 deletions
diff --git a/gio/gsubprocess.c b/gio/gsubprocess.c index 665d729ed..77a23efc3 100644 --- a/gio/gsubprocess.c +++ b/gio/gsubprocess.c @@ -179,160 +179,6 @@ enum N_PROPS }; -#ifdef G_OS_UNIX -typedef struct -{ - gint fds[3]; - GSpawnChildSetupFunc child_setup_func; - gpointer child_setup_data; - GArray *basic_fd_assignments; - GArray *needdup_fd_assignments; -} ChildData; - -static void -unset_cloexec (int fd) -{ - int flags; - int result; - - flags = fcntl (fd, F_GETFD, 0); - - if (flags != -1) - { - int errsv; - flags &= (~FD_CLOEXEC); - do - { - result = fcntl (fd, F_SETFD, flags); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - } -} - -static int -dupfd_cloexec (int parent_fd) -{ - int fd, errsv; -#ifdef F_DUPFD_CLOEXEC - do - { - fd = fcntl (parent_fd, F_DUPFD_CLOEXEC, 3); - errsv = errno; - } - while (fd == -1 && errsv == EINTR); -#else - /* OS X Snow Lion and earlier don't have F_DUPFD_CLOEXEC: - * https://bugzilla.gnome.org/show_bug.cgi?id=710962 - */ - int result, flags; - do - { - fd = fcntl (parent_fd, F_DUPFD, 3); - errsv = errno; - } - while (fd == -1 && errsv == EINTR); - flags = fcntl (fd, F_GETFD, 0); - if (flags != -1) - { - flags |= FD_CLOEXEC; - do - { - result = fcntl (fd, F_SETFD, flags); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - } -#endif - return fd; -} - -/* - * Based on code derived from - * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(), - * used under the LGPLv2+ with permission from author. - */ -static void -child_setup (gpointer user_data) -{ - ChildData *child_data = user_data; - guint i; - gint result; - int errsv; - - /* We're on the child side now. "Rename" the file descriptors in - * child_data.fds[] to stdin/stdout/stderr. - * - * We don't close the originals. It's possible that the originals - * should not be closed and if they should be closed then they should - * have been created O_CLOEXEC. - */ - for (i = 0; i < 3; i++) - if (child_data->fds[i] != -1 && child_data->fds[i] != (gint) i) - { - do - { - result = dup2 (child_data->fds[i], i); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - } - - /* Basic fd assignments we can just unset FD_CLOEXEC */ - if (child_data->basic_fd_assignments) - { - for (i = 0; i < child_data->basic_fd_assignments->len; i++) - { - gint fd = g_array_index (child_data->basic_fd_assignments, int, i); - - unset_cloexec (fd); - } - } - - /* If we're doing remapping fd assignments, we need to handle - * the case where the user has specified e.g.: - * 5 -> 4, 4 -> 6 - * - * We do this by duping the source fds temporarily. - */ - if (child_data->needdup_fd_assignments) - { - for (i = 0; i < child_data->needdup_fd_assignments->len; i += 2) - { - gint parent_fd = g_array_index (child_data->needdup_fd_assignments, int, i); - gint new_parent_fd; - - new_parent_fd = dupfd_cloexec (parent_fd); - - g_array_index (child_data->needdup_fd_assignments, int, i) = new_parent_fd; - } - for (i = 0; i < child_data->needdup_fd_assignments->len; i += 2) - { - gint parent_fd = g_array_index (child_data->needdup_fd_assignments, int, i); - gint child_fd = g_array_index (child_data->needdup_fd_assignments, int, i+1); - - if (parent_fd == child_fd) - { - unset_cloexec (parent_fd); - } - else - { - do - { - result = dup2 (parent_fd, child_fd); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - (void) close (parent_fd); - } - } - } - - if (child_data->child_setup_func) - child_data->child_setup_func (child_data->child_setup_data); -} -#endif - static GInputStream * platform_input_stream_from_spawn_fd (gint fd) { @@ -450,12 +296,12 @@ initable_init (GInitable *initable, GError **error) { GSubprocess *self = G_SUBPROCESS (initable); -#ifdef G_OS_UNIX - ChildData child_data = { { -1, -1, -1 }, 0, NULL, NULL, NULL }; -#endif gint *pipe_ptrs[3] = { NULL, NULL, NULL }; gint pipe_fds[3] = { -1, -1, -1 }; gint close_fds[3] = { -1, -1, -1 }; +#ifdef G_OS_UNIX + gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; +#endif GSpawnFlags spawn_flags = 0; gboolean success = FALSE; gint i; @@ -480,11 +326,11 @@ initable_init (GInitable *initable, else if (self->launcher) { if (self->launcher->stdin_fd != -1) - child_data.fds[0] = self->launcher->stdin_fd; + stdin_fd = self->launcher->stdin_fd; else if (self->launcher->stdin_path != NULL) { - child_data.fds[0] = close_fds[0] = unix_open_file (self->launcher->stdin_path, O_RDONLY, error); - if (child_data.fds[0] == -1) + stdin_fd = close_fds[0] = unix_open_file (self->launcher->stdin_path, O_RDONLY, error); + if (stdin_fd == -1) goto out; } } @@ -499,11 +345,11 @@ initable_init (GInitable *initable, else if (self->launcher) { if (self->launcher->stdout_fd != -1) - child_data.fds[1] = self->launcher->stdout_fd; + stdout_fd = self->launcher->stdout_fd; else if (self->launcher->stdout_path != NULL) { - child_data.fds[1] = close_fds[1] = unix_open_file (self->launcher->stdout_path, O_CREAT | O_WRONLY, error); - if (child_data.fds[1] == -1) + stdout_fd = close_fds[1] = unix_open_file (self->launcher->stdout_path, O_CREAT | O_WRONLY, error); + if (stdout_fd == -1) goto out; } } @@ -516,29 +362,21 @@ initable_init (GInitable *initable, pipe_ptrs[2] = &pipe_fds[2]; #ifdef G_OS_UNIX else if (self->flags & G_SUBPROCESS_FLAGS_STDERR_MERGE) - /* This will work because stderr gets setup after stdout. */ - child_data.fds[2] = 1; + /* This will work because stderr gets set up after stdout. */ + stderr_fd = 1; else if (self->launcher) { if (self->launcher->stderr_fd != -1) - child_data.fds[2] = self->launcher->stderr_fd; + stderr_fd = self->launcher->stderr_fd; else if (self->launcher->stderr_path != NULL) { - child_data.fds[2] = close_fds[2] = unix_open_file (self->launcher->stderr_path, O_CREAT | O_WRONLY, error); - if (child_data.fds[2] == -1) + stderr_fd = close_fds[2] = unix_open_file (self->launcher->stderr_path, O_CREAT | O_WRONLY, error); + if (stderr_fd == -1) goto out; } } #endif -#ifdef G_OS_UNIX - if (self->launcher) - { - child_data.basic_fd_assignments = self->launcher->basic_fd_assignments; - child_data.needdup_fd_assignments = self->launcher->needdup_fd_assignments; - } -#endif - /* argv0 has no '/' in it? We better do a PATH lookup. */ if (strchr (self->argv[0], G_DIR_SEPARATOR) == NULL) { @@ -554,23 +392,25 @@ initable_init (GInitable *initable, spawn_flags |= G_SPAWN_DO_NOT_REAP_CHILD; spawn_flags |= G_SPAWN_CLOEXEC_PIPES; + success = g_spawn_async_with_pipes_and_fds (self->launcher ? self->launcher->cwd : NULL, + (const gchar * const *) self->argv, + (const gchar * const *) (self->launcher ? self->launcher->envp : NULL), + spawn_flags, #ifdef G_OS_UNIX - child_data.child_setup_func = self->launcher ? self->launcher->child_setup_func : NULL; - child_data.child_setup_data = self->launcher ? self->launcher->child_setup_user_data : NULL; -#endif - - success = g_spawn_async_with_pipes (self->launcher ? self->launcher->cwd : NULL, - self->argv, - self->launcher ? self->launcher->envp : NULL, - spawn_flags, -#ifdef G_OS_UNIX - child_setup, &child_data, + self->launcher ? self->launcher->child_setup_func : NULL, + self->launcher ? self->launcher->child_setup_user_data : NULL, + stdin_fd, stdout_fd, stderr_fd, + self->launcher ? (const gint *) self->launcher->source_fds->data : NULL, + self->launcher ? (const gint *) self->launcher->target_fds->data : NULL, + self->launcher ? self->launcher->source_fds->len : 0, #else - NULL, NULL, + NULL, NULL, + -1, -1, -1, + NULL, NULL, 0, #endif - &self->pid, - pipe_ptrs[0], pipe_ptrs[1], pipe_ptrs[2], - error); + &self->pid, + pipe_ptrs[0], pipe_ptrs[1], pipe_ptrs[2], + error); g_assert (success == (self->pid != 0)); { |