summaryrefslogtreecommitdiffstats
path: root/Lib/subprocess.py
diff options
context:
space:
mode:
authorGregory P. Smith <greg@mad-scientist.com>2010-12-14 13:43:30 (GMT)
committerGregory P. Smith <greg@mad-scientist.com>2010-12-14 13:43:30 (GMT)
commit8edd99d0852c45f70b6abc851e6b326d4250cd33 (patch)
tree739c5f3039791b749228455076e6af2d89d71b8c /Lib/subprocess.py
parent39f34aa1f3c1f02d72ec28d0d177834e22dfc89b (diff)
downloadcpython-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.py47
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: