From 2054ccad95cfdcf5eccd2ef6847c12039c9678e8 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Sat, 10 Nov 2012 13:16:29 -0500 Subject: [PATCH] gspawn: support creating pipes with O_CLOEXEC Add a new flag, G_SPAWN_CLOEXEC_PIPES, for creating the stdin/out/err pipes with O_CLOEXEC (for the usual reasons). https://bugzilla.gnome.org/show_bug.cgi?id=672102 --- glib/gspawn.c | 37 +++++++++++-------------------------- glib/gspawn.h | 5 ++++- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/glib/gspawn.c b/glib/gspawn.c index 3545a78..718cc62 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -53,7 +53,7 @@ #include "gtestutils.h" #include "gutils.h" #include "glibintl.h" - +#include "glib-unix.h" /** * SECTION:spawn @@ -69,8 +69,6 @@ static gint g_execute (const gchar *file, gboolean search_path, gboolean search_path_from_envp); -static gboolean make_pipe (gint p[2], - GError **error); static gboolean fork_exec_with_pipes (gboolean intermediate_child, const gchar *working_directory, gchar **argv, @@ -82,6 +80,7 @@ static gboolean fork_exec_with_pipes (gboolean intermediate_child, 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, @@ -312,6 +311,7 @@ g_spawn_sync (const gchar *working_directory, (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, @@ -679,6 +679,7 @@ g_spawn_async_with_pipes (const gchar *working_directory, (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, @@ -1311,6 +1312,7 @@ fork_exec_with_pipes (gboolean intermediate_child, 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, @@ -1325,21 +1327,22 @@ fork_exec_with_pipes (gboolean intermediate_child, gint stderr_pipe[2] = { -1, -1 }; gint child_err_report_pipe[2] = { -1, -1 }; gint child_pid_report_pipe[2] = { -1, -1 }; + guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0; gint status; - if (!make_pipe (child_err_report_pipe, error)) + if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error)) return FALSE; - if (intermediate_child && !make_pipe (child_pid_report_pipe, error)) + if (intermediate_child && !g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error)) goto cleanup_and_fail; - if (standard_input && !make_pipe (stdin_pipe, error)) + if (standard_input && !g_unix_open_pipe (stdin_pipe, pipe_flags, error)) goto cleanup_and_fail; - if (standard_output && !make_pipe (stdout_pipe, error)) + if (standard_output && !g_unix_open_pipe (stdout_pipe, pipe_flags, error)) goto cleanup_and_fail; - if (standard_error && !make_pipe (stderr_pipe, error)) + if (standard_error && !g_unix_open_pipe (stderr_pipe, FD_CLOEXEC, error)) goto cleanup_and_fail; pid = fork (); @@ -1623,24 +1626,6 @@ fork_exec_with_pipes (gboolean intermediate_child, return FALSE; } -static gboolean -make_pipe (gint p[2], - GError **error) -{ - if (pipe (p) < 0) - { - gint errsv = errno; - g_set_error (error, - G_SPAWN_ERROR, - G_SPAWN_ERROR_FAILED, - _("Failed to create pipe for communicating with child process (%s)"), - g_strerror (errsv)); - return FALSE; - } - else - return TRUE; -} - /* Based on execvp from GNU C Library */ static void diff --git a/glib/gspawn.h b/glib/gspawn.h index 1120d81..c5586b1 100644 --- a/glib/gspawn.h +++ b/glib/gspawn.h @@ -166,6 +166,8 @@ typedef void (* GSpawnChildSetupFunc) (gpointer user_data); * @G_SPAWN_SEARCH_PATH_FROM_ENVP: if argv[0] is not an abolute path, * it will be looked for in the PATH from the passed child * environment. Since: 2.34 + * @G_SPAWN_CLOEXEC_PIPES: On UNIX, returned pipe file descriptors will have the + * close-on-exec flag set. Since: 2.36 * * Flags passed to g_spawn_sync(), g_spawn_async() and g_spawn_async_with_pipes(). */ @@ -180,7 +182,8 @@ typedef enum G_SPAWN_STDERR_TO_DEV_NULL = 1 << 4, G_SPAWN_CHILD_INHERITS_STDIN = 1 << 5, G_SPAWN_FILE_AND_ARGV_ZERO = 1 << 6, - G_SPAWN_SEARCH_PATH_FROM_ENVP = 1 << 7 + G_SPAWN_SEARCH_PATH_FROM_ENVP = 1 << 7, + G_SPAWN_CLOEXEC_PIPES = 1 << 8 } GSpawnFlags; GQuark g_spawn_error_quark (void); -- 2.7.4