summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-01-03 18:23:55 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-01-03 18:23:55 (GMT)
commitc9c83ba8969c166f617da24c6af54a479373adf9 (patch)
treecb3e91db6e838110339f8f16ee9c77c52a68ffec /Modules
parent63ebe1c3093bd40ea5a7e1a225ea0355f13563b4 (diff)
downloadcpython-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.c29
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));
}