From 44a82bf84cf77f87b70a5108372b7d869bac8aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 4 Apr 2022 15:46:23 +0400 Subject: [PATCH] glib/win32: fix spawn from GUI regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 674072b13 ("glib/win32: check if dup() failed in helper process"), I happily added checks for dup() calls in the spawn helper. However, I didn't realize that GUI applications do not necessarily have a console attached, and will now fail spawning processes. One way to check that is via a _fileno() call, as explained in: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fileno?view=msvc-170#return-value Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2628 Signed-off-by: Marc-André Lureau --- glib/gspawn-win32-helper.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/glib/gspawn-win32-helper.c b/glib/gspawn-win32-helper.c index 2ca9009a4..4729ee46e 100644 --- a/glib/gspawn-win32-helper.c +++ b/glib/gspawn-win32-helper.c @@ -292,9 +292,13 @@ main (int ignored_argc, char **ignored_argv) checked_dup2 (fd, 1, child_err_report_fd); } - saved_stderr_fd = reopen_noninherited (dup (2), _O_WRONLY); - if (saved_stderr_fd == -1) - write_err_and_exit (child_err_report_fd, CHILD_DUP_FAILED); + /* GUI application do not necessarily have a stderr */ + if (_fileno (stderr) == 2) + { + saved_stderr_fd = reopen_noninherited (dup (2), _O_WRONLY); + if (saved_stderr_fd == -1) + write_err_and_exit (child_err_report_fd, CHILD_DUP_FAILED); + } maxfd = MAX (saved_stderr_fd, maxfd); if (argv[ARG_STDERR][0] == '-') @@ -354,8 +358,11 @@ main (int ignored_argc, char **ignored_argv) 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); - maxfd++; - saved_stderr_fd = checked_dup2 (saved_stderr_fd, maxfd, child_err_report_fd); + if (saved_stderr_fd >= 0) + { + maxfd++; + saved_stderr_fd = checked_dup2 (saved_stderr_fd, maxfd, child_err_report_fd); + } { GHashTableIter iter; @@ -381,7 +388,8 @@ main (int ignored_argc, char **ignored_argv) g_hash_table_add (fds, GINT_TO_POINTER (child_err_report_fd)); g_hash_table_add (fds, GINT_TO_POINTER (helper_sync_fd)); - g_hash_table_add (fds, GINT_TO_POINTER (saved_stderr_fd)); + if (saved_stderr_fd >= 0) + g_hash_table_add (fds, GINT_TO_POINTER (saved_stderr_fd)); /* argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3 * upwards should be closed @@ -430,7 +438,9 @@ main (int ignored_argc, char **ignored_argv) * Remove redirection so that they would go to original stderr * instead of being treated as part of stderr of child process. */ - dup2 (saved_stderr_fd, 2); + if (saved_stderr_fd >= 0) + dup2 (saved_stderr_fd, 2); + if (handle == -1 && saved_errno != 0) { int ec = (saved_errno == ENOENT)