From e05227371dbd35300e13328e9c0ce275b88108a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 4 Feb 2022 12:30:10 +0400 Subject: [PATCH] glib/win32: fix passing same fd for stdout & stderr spawn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delay closing the FDs after all input FDs are duped. Signed-off-by: Marc-André Lureau --- glib/gspawn-win32-helper.c | 27 ++++++++++++--------------- glib/gspawn.c | 4 ---- glib/tests/spawn-singlethread.c | 2 -- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/glib/gspawn-win32-helper.c b/glib/gspawn-win32-helper.c index 58fd719fa..2ca9009a4 100644 --- a/glib/gspawn-win32-helper.c +++ b/glib/gspawn-win32-helper.c @@ -154,7 +154,7 @@ protect_wargv (gint argc, } static int -checked_dup2 (int oldfd, int newfd, int report_fd, gboolean close_old) +checked_dup2 (int oldfd, int newfd, int report_fd) { if (oldfd == newfd) return newfd; @@ -162,9 +162,6 @@ checked_dup2 (int oldfd, int newfd, int report_fd, gboolean close_old) if (dup2 (oldfd, newfd) == -1) write_err_and_exit (report_fd, CHILD_DUP_FAILED); - if (close_old) - close (oldfd); - return newfd; } @@ -274,12 +271,12 @@ main (int ignored_argc, char **ignored_argv) else if (argv[ARG_STDIN][0] == 'z') { fd = open ("NUL:", O_RDONLY); - checked_dup2 (fd, 0, child_err_report_fd, TRUE); + checked_dup2 (fd, 0, child_err_report_fd); } else { fd = atoi (argv[ARG_STDIN]); - checked_dup2 (fd, 0, child_err_report_fd, TRUE); + checked_dup2 (fd, 0, child_err_report_fd); } if (argv[ARG_STDOUT][0] == '-') @@ -287,12 +284,12 @@ main (int ignored_argc, char **ignored_argv) else if (argv[ARG_STDOUT][0] == 'z') { fd = open ("NUL:", O_WRONLY); - checked_dup2 (fd, 1, child_err_report_fd, TRUE); + checked_dup2 (fd, 1, child_err_report_fd); } else { fd = atoi (argv[ARG_STDOUT]); - checked_dup2 (fd, 1, child_err_report_fd, TRUE); + checked_dup2 (fd, 1, child_err_report_fd); } saved_stderr_fd = reopen_noninherited (dup (2), _O_WRONLY); @@ -305,12 +302,12 @@ main (int ignored_argc, char **ignored_argv) else if (argv[ARG_STDERR][0] == 'z') { fd = open ("NUL:", O_WRONLY); - checked_dup2 (fd, 2, child_err_report_fd, TRUE); + checked_dup2 (fd, 2, child_err_report_fd); } else { fd = atoi (argv[ARG_STDERR]); - checked_dup2 (fd, 2, child_err_report_fd, TRUE); + checked_dup2 (fd, 2, child_err_report_fd); } /* argv[ARG_WORKING_DIRECTORY] is the directory in which to run the @@ -354,11 +351,11 @@ main (int ignored_argc, char **ignored_argv) } maxfd++; - child_err_report_fd = checked_dup2 (child_err_report_fd, maxfd, child_err_report_fd, TRUE); + child_err_report_fd = checked_dup2 (child_err_report_fd, maxfd, child_err_report_fd); maxfd++; - helper_sync_fd = checked_dup2 (helper_sync_fd, maxfd, child_err_report_fd, TRUE); + helper_sync_fd = checked_dup2 (helper_sync_fd, maxfd, child_err_report_fd); maxfd++; - saved_stderr_fd = checked_dup2 (saved_stderr_fd, maxfd, child_err_report_fd, TRUE); + saved_stderr_fd = checked_dup2 (saved_stderr_fd, maxfd, child_err_report_fd); { GHashTableIter iter; @@ -373,13 +370,13 @@ main (int ignored_argc, char **ignored_argv) * fds are larger than any target fd to avoid introducing new conflicts. */ maxfd++; - checked_dup2 (GPOINTER_TO_INT (sourcefd), maxfd, child_err_report_fd, TRUE); + checked_dup2 (GPOINTER_TO_INT (sourcefd), maxfd, child_err_report_fd); g_hash_table_iter_replace (&iter, GINT_TO_POINTER (maxfd)); } g_hash_table_iter_init (&iter, fds); while (g_hash_table_iter_next (&iter, &targetfd, &sourcefd)) - checked_dup2 (GPOINTER_TO_INT (sourcefd), GPOINTER_TO_INT (targetfd), child_err_report_fd, TRUE); + checked_dup2 (GPOINTER_TO_INT (sourcefd), GPOINTER_TO_INT (targetfd), child_err_report_fd); } g_hash_table_add (fds, GINT_TO_POINTER (child_err_report_fd)); diff --git a/glib/gspawn.c b/glib/gspawn.c index 60da07198..1128221cc 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -856,8 +856,6 @@ g_spawn_async_with_pipes (const gchar *working_directory, * windows on the right screen, you may want to use #GdkAppLaunchContext, * #GAppLaunchContext, or set the `DISPLAY` environment variable. * - * On Windows, sharing the same FD for @stdout_fd and @stderr_fd is not supported. - * * Returns: %TRUE on success, %FALSE if an error was set * * Since: 2.68 @@ -940,8 +938,6 @@ g_spawn_async_with_pipes_and_fds (const gchar *working_directory, * Identical to g_spawn_async_with_pipes_and_fds() but with `n_fds` set to zero, * so no FD assignments are used. * - * On Windows, sharing the same FD for @stdout_fd and @stderr_fd is not supported. - * * Returns: %TRUE on success, %FALSE if an error was set * * Since: 2.58 diff --git a/glib/tests/spawn-singlethread.c b/glib/tests/spawn-singlethread.c index 159e8c34a..7711ba8fe 100644 --- a/glib/tests/spawn-singlethread.c +++ b/glib/tests/spawn-singlethread.c @@ -196,9 +196,7 @@ test_spawn_async_with_fds (void) { NO_FD, NO_FD, NO_FD }, /* Test with no fds passed */ { NO_FD, FD_NEGATIVE, NO_FD }, /* Test another negative fd value */ { PIPE, PIPE, PIPE }, /* Test with unique fds passed */ -#ifndef G_OS_WIN32 { NO_FD, PIPE, STDOUT_PIPE }, /* Test the same fd for stdout + stderr */ -#endif }; arg = g_strdup_printf ("thread %d", tnum);