diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-01-03 18:23:55 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-01-03 18:23:55 (GMT) |
commit | c9c83ba8969c166f617da24c6af54a479373adf9 (patch) | |
tree | cb3e91db6e838110339f8f16ee9c77c52a68ffec /Modules | |
parent | 63ebe1c3093bd40ea5a7e1a225ea0355f13563b4 (diff) | |
download | cpython-c9c83ba8969c166f617da24c6af54a479373adf9.zip cpython-c9c83ba8969c166f617da24c6af54a479373adf9.tar.gz cpython-c9c83ba8969c166f617da24c6af54a479373adf9.tar.bz2 |
Issue #10806, issue #9905: Fix subprocess pipes when some of the standard
file descriptors (0, 1, 2) are closed in the parent process. Initial
patch by Ross Lagerwall.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_posixsubprocess.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index a175d42..0f85da9 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -69,27 +69,40 @@ static void child_exec(char *const exec_array[], } POSIX_CALL(close(errpipe_read)); - /* Dup fds for child. */ - if (p2cread != -1) { + /* Dup fds for child. + dup2() removes the CLOEXEC flag but we must do it ourselves if dup2() + would be a no-op (issue #10806). */ + if (p2cread == 0) { + int old = fcntl(p2cread, F_GETFD); + if (old != -1) + fcntl(p2cread, F_SETFD, old & ~FD_CLOEXEC); + } else if (p2cread != -1) { POSIX_CALL(dup2(p2cread, 0)); /* stdin */ } - if (c2pwrite != -1) { + if (c2pwrite == 1) { + int old = fcntl(c2pwrite, F_GETFD); + if (old != -1) + fcntl(c2pwrite, F_SETFD, old & ~FD_CLOEXEC); + } else if (c2pwrite != -1) { POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */ } - if (errwrite != -1) { + if (errwrite == 2) { + int old = fcntl(errwrite, F_GETFD); + if (old != -1) + fcntl(errwrite, F_SETFD, old & ~FD_CLOEXEC); + } else if (errwrite != -1) { POSIX_CALL(dup2(errwrite, 2)); /* stderr */ } /* Close pipe fds. Make sure we don't close the same fd more than */ /* once, or standard fds. */ - if (p2cread != -1 && p2cread != 0) { + if (p2cread > 2) { POSIX_CALL(close(p2cread)); } - if (c2pwrite != -1 && c2pwrite != p2cread && c2pwrite != 1) { + if (c2pwrite > 2) { POSIX_CALL(close(c2pwrite)); } - if (errwrite != -1 && errwrite != p2cread && - errwrite != c2pwrite && errwrite != 2) { + if (errwrite != c2pwrite && errwrite > 2) { POSIX_CALL(close(errwrite)); } |