diff options
author | Gregory P. Smith <greg@mad-scientist.com> | 2010-12-14 13:43:30 (GMT) |
---|---|---|
committer | Gregory P. Smith <greg@mad-scientist.com> | 2010-12-14 13:43:30 (GMT) |
commit | 8edd99d0852c45f70b6abc851e6b326d4250cd33 (patch) | |
tree | 739c5f3039791b749228455076e6af2d89d71b8c /Lib/subprocess.py | |
parent | 39f34aa1f3c1f02d72ec28d0d177834e22dfc89b (diff) | |
download | cpython-8edd99d0852c45f70b6abc851e6b326d4250cd33.zip cpython-8edd99d0852c45f70b6abc851e6b326d4250cd33.tar.gz cpython-8edd99d0852c45f70b6abc851e6b326d4250cd33.tar.bz2 |
Issue #6559: fix the subprocess.Popen pass_fds implementation. Add a unittest.
Issue #7213: Change the close_fds default on Windows to better match the new
default on POSIX. True when possible (False if stdin/stdout/stderr are
supplied).
Update the documentation to reflect all of the above.
Diffstat (limited to 'Lib/subprocess.py')
-rw-r--r-- | Lib/subprocess.py | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 729a53b..ac46ce8 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -27,10 +27,10 @@ This module defines one class called Popen: class Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=_PLATFORM_DEFAULT, shell=False, + preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, - restore_signals=True, start_new_session=False): + restore_signals=True, start_new_session=False, pass_fds=()): Arguments are: @@ -81,8 +81,11 @@ is executed. If close_fds is true, all file descriptors except 0, 1 and 2 will be closed before the child process is executed. The default for close_fds -varies by platform: False on Windows and True on all other platforms -such as POSIX. +varies by platform: Always true on POSIX. True when stdin/stdout/stderr +are None on Windows, false otherwise. + +pass_fds is an optional sequence of file descriptors to keep open between the +parent and child. Providing any pass_fds implicitly sets close_fds to true. if shell is true, the specified command will be executed through the shell. @@ -621,17 +624,14 @@ def getoutput(cmd): return getstatusoutput(cmd)[1] -if mswindows: - _PLATFORM_DEFAULT = False -else: - _PLATFORM_DEFAULT = True +_PLATFORM_DEFAULT_CLOSE_FDS = object() class Popen(object): def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=_PLATFORM_DEFAULT, shell=False, - cwd=None, env=None, universal_newlines=False, + preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS, + shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=()): @@ -648,12 +648,24 @@ class Popen(object): if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows " "platforms") - if close_fds and (stdin is not None or stdout is not None or - stderr is not None): - raise ValueError("close_fds is not supported on Windows " - "platforms if you redirect stdin/stdout/stderr") + any_stdio_set = (stdin is not None or stdout is not None or + stderr is not None) + if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS: + if any_stdio_set: + close_fds = False + else: + close_fds = True + elif close_fds and any_stdio_set: + raise ValueError( + "close_fds is not supported on Windows platforms" + " if you redirect stdin/stdout/stderr") else: # POSIX + if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS: + close_fds = True + if pass_fds and not close_fds: + warnings.warn("pass_fds overriding close_fds.", RuntimeWarning) + close_fds = True if startupinfo is not None: raise ValueError("startupinfo is only supported on Windows " "platforms") @@ -661,9 +673,6 @@ class Popen(object): raise ValueError("creationflags is only supported on Windows " "platforms") - if pass_fds and not close_fds: - raise ValueError("pass_fds requires close_fds=True.") - self.stdin = None self.stdout = None self.stderr = None @@ -876,7 +885,7 @@ class Popen(object): unused_restore_signals, unused_start_new_session): """Execute program (MS Windows version)""" - assert not pass_fds, "pass_fds not yet supported on Windows" + assert not pass_fds, "pass_fds not supported on Windows." if not isinstance(args, str): args = list2cmdline(args) @@ -1091,7 +1100,7 @@ class Popen(object): # precondition: fds_to_keep must be sorted and unique start_fd = 3 for fd in fds_to_keep: - if fd > start_fd: + if fd >= start_fd: os.closerange(start_fd, fd) start_fd = fd + 1 if start_fd <= MAXFD: |