gspawn: Avoid merged FDs being closed on exec()

If `stdout_fd` was set to (say) 6, and `stderr_fd` was set to 1, the
`set_cloexec()` call for setting up `stderr` would set the new `stdout`
for the forked process to be closed in the pending `exec()`.

This would cause the child process to error when writing to `stdout`.

This situation happens when using `G_SUBPROCESS_FLAGS_STDERR_MERGE`.

Add some conditions to prevent setting `CLOEXEC` in such cases.

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

Helps: #2097
This commit is contained in:
Philip Withnall 2020-12-04 18:28:08 +00:00
parent f20f0d385e
commit c5f3ba7f01

View File

@ -1497,7 +1497,9 @@ do_exec (gint child_err_report_fd,
write_err_and_exit (child_err_report_fd,
CHILD_DUP2_FAILED);
set_cloexec (GINT_TO_POINTER(0), stdin_fd);
if (!((stdout_fd >= 0 || stdout_to_null) && stdin_fd == 1) &&
!((stderr_fd >= 0 || stderr_to_null) && stdin_fd == 2))
set_cloexec (GINT_TO_POINTER(0), stdin_fd);
}
else if (!child_inherits_stdin)
{
@ -1517,7 +1519,9 @@ do_exec (gint child_err_report_fd,
write_err_and_exit (child_err_report_fd,
CHILD_DUP2_FAILED);
set_cloexec (GINT_TO_POINTER(0), stdout_fd);
if (!((stdin_fd >= 0 || !child_inherits_stdin) && stdout_fd == 0) &&
!((stderr_fd >= 0 || stderr_to_null) && stdout_fd == 2))
set_cloexec (GINT_TO_POINTER(0), stdout_fd);
}
else if (stdout_to_null)
{
@ -1536,7 +1540,9 @@ do_exec (gint child_err_report_fd,
write_err_and_exit (child_err_report_fd,
CHILD_DUP2_FAILED);
set_cloexec (GINT_TO_POINTER(0), stderr_fd);
if (!((stdin_fd >= 0 || !child_inherits_stdin) && stderr_fd == 0) &&
!((stdout_fd >= 0 || stdout_to_null) && stderr_fd == 1))
set_cloexec (GINT_TO_POINTER(0), stderr_fd);
}
else if (stderr_to_null)
{