[Python-checkins] cpython (merge 3.4 -> 3.4): Merge heads

serhiy.storchaka python-checkins at python.org
Sun Sep 21 21:30:45 CEST 2014


https://hg.python.org/cpython/rev/ba5d3b4b4260
changeset: 92506:ba5d3b4b4260
branch: 3.4
parent: 92504:176579df4edd
parent: 92501:38867f90f1d9
user: Serhiy Storchaka <storchaka at gmail.com>
date: Sun Sep 21 22:25:25 2014 +0300
summary:
 Merge heads
files:
 Doc/library/subprocess.rst | 18 +++++++++----
 Lib/subprocess.py | 3 +-
 Lib/test/test_subprocess.py | 33 +++++++++++++++++++++++++
 Misc/NEWS | 3 ++
 4 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -406,12 +406,18 @@
 
 Read the `Security Considerations`_ section before using ``shell=True``.
 
- *bufsize* will be supplied as the corresponding argument to the :func:`open`
- function when creating the stdin/stdout/stderr pipe file objects: :const:`0`
- means unbuffered (read and write are one system call and can return short),
- :const:`1` means line buffered, any other positive value means use a buffer
- of approximately that size. A negative bufsize (the default) means the
- system default of io.DEFAULT_BUFFER_SIZE will be used.
+ *bufsize* will be supplied as the corresponding argument to the
+ :func:`open` function when creating the stdin/stdout/stderr pipe
+ file objects:
+
+ - :const:`0` means unbuffered (read and write are one
+ system call and can return short)
+ - :const:`1` means line buffered
+ (only usable if ``universal_newlines=True`` i.e., in a text mode)
+ - any other positive value means use a buffer of approximately that
+ size
+ - negative bufsize (the default) means the system default of
+ io.DEFAULT_BUFFER_SIZE will be used.
 
 .. versionchanged:: 3.3.1
 *bufsize* now defaults to -1 to enable buffering by default to match the
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -837,7 +837,8 @@
 if p2cwrite != -1:
 self.stdin = io.open(p2cwrite, 'wb', bufsize)
 if universal_newlines:
- self.stdin = io.TextIOWrapper(self.stdin, write_through=True)
+ self.stdin = io.TextIOWrapper(self.stdin, write_through=True,
+ line_buffering=(bufsize == 1))
 if c2pread != -1:
 self.stdout = io.open(c2pread, 'rb', bufsize)
 if universal_newlines:
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -1008,6 +1008,39 @@
 p = subprocess.Popen([sys.executable, "-c", "pass"], bufsize=None)
 self.assertEqual(p.wait(), 0)
 
+ def _test_bufsize_equal_one(self, line, expected, universal_newlines):
+ # subprocess may deadlock with bufsize=1, see issue #21332
+ with subprocess.Popen([sys.executable, "-c", "import sys;"
+ "sys.stdout.write(sys.stdin.readline());"
+ "sys.stdout.flush()"],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL,
+ bufsize=1,
+ universal_newlines=universal_newlines) as p:
+ p.stdin.write(line) # expect that it flushes the line in text mode
+ os.close(p.stdin.fileno()) # close it without flushing the buffer
+ read_line = p.stdout.readline()
+ try:
+ p.stdin.close()
+ except OSError:
+ pass
+ p.stdin = None
+ self.assertEqual(p.returncode, 0)
+ self.assertEqual(read_line, expected)
+
+ def test_bufsize_equal_one_text_mode(self):
+ # line is flushed in text mode with bufsize=1.
+ # we should get the full line in return
+ line = "line\n"
+ self._test_bufsize_equal_one(line, line, universal_newlines=True)
+
+ def test_bufsize_equal_one_binary_mode(self):
+ # line is not flushed in binary mode with bufsize=1.
+ # we should get empty response
+ line = b'line' + os.linesep.encode() # assume ascii-based locale
+ self._test_bufsize_equal_one(line, b'', universal_newlines=False)
+
 def test_leaking_fds_on_error(self):
 # see bug #5179: Popen leaks file descriptors to PIPEs if
 # the child fails to execute; this will eventually exhaust
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -35,6 +35,9 @@
 - Issue #22423: Unhandled exception in thread no longer causes unhandled
 AttributeError when sys.stderr is None.
 
+- Issue #21332: Ensure that ``bufsize=1`` in subprocess.Popen() selects
+ line buffering, rather than block buffering. Patch by Akira Li.
+
 - Issue #21091: Fix API bug: email.message.EmailMessage.is_attachment is now
 a method. Since EmailMessage is provisional, we can change the API in a
 maintenance release, but we use a trick to remain backward compatible with
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /