diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-01-03 18:36:36 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-01-03 18:36:36 (GMT) |
commit | f50a6b6b6d5c7b36e7fbe49266edd3083a23cbb9 (patch) | |
tree | 722051f4f6c38f4df014b81126ddb9c7f881433a /Lib/subprocess.py | |
parent | 904fe042f3750df886e6a86aa660c1f047c9d0c5 (diff) | |
download | cpython-f50a6b6b6d5c7b36e7fbe49266edd3083a23cbb9.zip cpython-f50a6b6b6d5c7b36e7fbe49266edd3083a23cbb9.tar.gz cpython-f50a6b6b6d5c7b36e7fbe49266edd3083a23cbb9.tar.bz2 |
Merged revisions 87695 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r87695 | antoine.pitrou | 2011-01-03 19:23:55 +0100 (lun., 03 janv. 2011) | 5 lines
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 'Lib/subprocess.py')
-rw-r--r-- | Lib/subprocess.py | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 5684d52..b8e3c0e 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1012,14 +1012,17 @@ class Popen(object): errread, errwrite) - def _set_cloexec_flag(self, fd): + def _set_cloexec_flag(self, fd, cloexec=True): try: cloexec_flag = fcntl.FD_CLOEXEC except AttributeError: cloexec_flag = 1 old = fcntl.fcntl(fd, fcntl.F_GETFD) - fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) + if cloexec: + fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) + else: + fcntl.fcntl(fd, fcntl.F_SETFD, old & ~cloexec_flag) def _close_fds(self, but): @@ -1080,23 +1083,25 @@ class Popen(object): os.close(errpipe_read) # Dup fds for child - if p2cread is not None: - os.dup2(p2cread, 0) - if c2pwrite is not None: - os.dup2(c2pwrite, 1) - if errwrite is not None: - os.dup2(errwrite, 2) + def _dup2(a, b): + # dup2() removes the CLOEXEC flag but + # we must do it ourselves if dup2() + # would be a no-op (issue #10806). + if a == b: + self._set_cloexec_flag(a, False) + elif a is not None: + os.dup2(a, b) + _dup2(p2cread, 0) + _dup2(c2pwrite, 1) + _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. - if p2cread is not None and p2cread not in (0,): - os.close(p2cread) - if c2pwrite is not None and \ - c2pwrite not in (p2cread, 1): - os.close(c2pwrite) - if (errwrite is not None and - errwrite not in (p2cread, c2pwrite, 2)): - os.close(errwrite) + closed = { None } + for fd in [p2cread, c2pwrite, errwrite]: + if fd not in closed and fd > 2: + os.close(fd) + closed.add(fd) # Close all other fds, if asked for if close_fds: |