[Python-checkins] r83945 - in python/branches/release31-maint: Lib/test/test_io.py Misc/ACKS Misc/NEWS Modules/_io/bufferedio.c
antoine.pitrou
python-checkins at python.org
Wed Aug 11 15:38:11 CEST 2010
Author: antoine.pitrou
Date: Wed Aug 11 15:38:10 2010
New Revision: 83945
Log:
Merged revisions 83944 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r83944 | antoine.pitrou | 2010-08-11 15:31:33 +0200 (mer., 11 août 2010) | 6 lines
Issue #9550: a BufferedReader could issue an additional read when the
original read request had been satisfied, which can block indefinitely
when the underlying raw IO channel is e.g. a socket. Report and original
patch by Jason V. Miller.
........
Modified:
python/branches/release31-maint/ (props changed)
python/branches/release31-maint/Lib/test/test_io.py
python/branches/release31-maint/Misc/ACKS
python/branches/release31-maint/Misc/NEWS
python/branches/release31-maint/Modules/_io/bufferedio.c
Modified: python/branches/release31-maint/Lib/test/test_io.py
==============================================================================
--- python/branches/release31-maint/Lib/test/test_io.py (original)
+++ python/branches/release31-maint/Lib/test/test_io.py Wed Aug 11 15:38:10 2010
@@ -51,12 +51,14 @@
self._read_stack = list(read_stack)
self._write_stack = []
self._reads = 0
+ self._extraneous_reads = 0
def read(self, n=None):
self._reads += 1
try:
return self._read_stack.pop(0)
except:
+ self._extraneous_reads += 1
return b""
def write(self, b):
@@ -87,6 +89,7 @@
try:
data = self._read_stack[0]
except IndexError:
+ self._extraneous_reads += 1
return 0
if data is None:
del self._read_stack[0]
@@ -822,6 +825,27 @@
self.assertRaises(IOError, bufio.seek, 0)
self.assertRaises(IOError, bufio.tell)
+ def test_no_extraneous_read(self):
+ # Issue #9550; when the raw IO object has satisfied the read request,
+ # we should not issue any additional reads, otherwise it may block
+ # (e.g. socket).
+ bufsize = 16
+ for n in (2, bufsize - 1, bufsize, bufsize + 1, bufsize * 2):
+ rawio = self.MockRawIO([b"x" * n])
+ bufio = self.tp(rawio, bufsize)
+ self.assertEqual(bufio.read(n), b"x" * n)
+ # Simple case: one raw read is enough to satisfy the request.
+ self.assertEqual(rawio._extraneous_reads, 0,
+ "failed for {}: {} != 0".format(n, rawio._extraneous_reads))
+ # A more complex case where two raw reads are needed to satisfy
+ # the request.
+ rawio = self.MockRawIO([b"x" * (n - 1), b"x"])
+ bufio = self.tp(rawio, bufsize)
+ self.assertEqual(bufio.read(n), b"x" * n)
+ self.assertEqual(rawio._extraneous_reads, 0,
+ "failed for {}: {} != 0".format(n, rawio._extraneous_reads))
+
+
class CBufferedReaderTest(BufferedReaderTest):
tp = io.BufferedReader
Modified: python/branches/release31-maint/Misc/ACKS
==============================================================================
--- python/branches/release31-maint/Misc/ACKS (original)
+++ python/branches/release31-maint/Misc/ACKS Wed Aug 11 15:38:10 2010
@@ -524,6 +524,7 @@
Aristotelis Mikropoulos
Damien Miller
Chad Miller
+Jason V. Miller
Jay T. Miller
Roman Milner
Andrii V. Mishkovskyi
Modified: python/branches/release31-maint/Misc/NEWS
==============================================================================
--- python/branches/release31-maint/Misc/NEWS (original)
+++ python/branches/release31-maint/Misc/NEWS Wed Aug 11 15:38:10 2010
@@ -93,6 +93,11 @@
Library
-------
+- Issue #9550: a BufferedReader could issue an additional read when the
+ original read request had been satisfied, which could block indefinitely
+ when the underlying raw IO channel was e.g. a socket. Report and original
+ patch by Jason V. Miller.
+
- Issue #6915: Under Windows, os.listdir() didn't release the Global
Interpreter Lock around all system calls. Original patch by Ryan Kelly.
Modified: python/branches/release31-maint/Modules/_io/bufferedio.c
==============================================================================
--- python/branches/release31-maint/Modules/_io/bufferedio.c (original)
+++ python/branches/release31-maint/Modules/_io/bufferedio.c Wed Aug 11 15:38:10 2010
@@ -1379,7 +1379,10 @@
self->pos = 0;
self->raw_pos = 0;
self->read_end = 0;
- while (self->read_end < self->buffer_size) {
+ /* NOTE: when the read is satisfied, we avoid issuing any additional
+ reads, which could block indefinitely (e.g. on a socket).
+ See issue #9550. */
+ while (remaining > 0 && self->read_end < self->buffer_size) {
Py_ssize_t r = _bufferedreader_fill_buffer(self);
if (r == -1)
goto error;
More information about the Python-checkins
mailing list