[Python-checkins] cpython (2.7): Issue #16133: The asynchat.async_chat.handle_read() method now ignores
victor.stinner
python-checkins at python.org
Thu Jul 24 19:15:42 CEST 2014
http://hg.python.org/cpython/rev/d422062d7d36
changeset: 91833:d422062d7d36
branch: 2.7
parent: 91830:841cdb6145e9
user: Victor Stinner <victor.stinner at gmail.com>
date: Thu Jul 24 19:15:00 2014 +0200
summary:
Issue #16133: The asynchat.async_chat.handle_read() method now ignores
socket.error() exceptions with blocking I/O errors: EAGAIN, EALREADY,
EINPROGRESS, or EWOULDBLOCK. Initial patch written by Xavier de Gaye.
files:
Doc/library/asyncore.rst | 5 ++++
Lib/asynchat.py | 9 ++++++-
Lib/test/test_asynchat.py | 32 ++++++++++++++++++++++++++-
Misc/NEWS | 4 +++
4 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/Doc/library/asyncore.rst b/Doc/library/asyncore.rst
--- a/Doc/library/asyncore.rst
+++ b/Doc/library/asyncore.rst
@@ -193,6 +193,11 @@
Read at most *buffer_size* bytes from the socket's remote end-point. An
empty string implies that the channel has been closed from the other end.
+ Note that :meth:`recv` may raise :exc:`socket.error` with
+ :data:`~errno.EAGAIN` or :data:`~errno.EWOULDBLOCK`, even though
+ :func:`select.select` or :func:`select.poll` has reported the socket
+ ready for reading.
+
.. method:: listen(backlog)
diff --git a/Lib/asynchat.py b/Lib/asynchat.py
--- a/Lib/asynchat.py
+++ b/Lib/asynchat.py
@@ -46,12 +46,17 @@
you - by calling your self.found_terminator() method.
"""
+import asyncore
+import errno
import socket
-import asyncore
from collections import deque
from sys import py3kwarning
from warnings import filterwarnings, catch_warnings
+_BLOCKING_IO_ERRORS = (errno.EAGAIN, errno.EALREADY, errno.EINPROGRESS,
+ errno.EWOULDBLOCK)
+
+
class async_chat (asyncore.dispatcher):
"""This is an abstract class. You must derive from this class, and add
the two methods collect_incoming_data() and found_terminator()"""
@@ -109,6 +114,8 @@
try:
data = self.recv (self.ac_in_buffer_size)
except socket.error, why:
+ if why.args[0] in _BLOCKING_IO_ERRORS:
+ return
self.handle_error()
return
diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py
--- a/Lib/test/test_asynchat.py
+++ b/Lib/test/test_asynchat.py
@@ -1,6 +1,10 @@
# test asynchat
-import asyncore, asynchat, socket, time
+import errno
+import asyncore
+import asynchat
+import socket
+import time
import unittest
import sys
from test import test_support
@@ -235,6 +239,31 @@
class TestAsynchat_WithPoll(TestAsynchat):
usepoll = True
+
+class TestAsynchatMocked(unittest.TestCase):
+ def test_blockingioerror(self):
+ # Issue #16133: handle_read() must ignore blocking I/O errors like
+ # EAGAIN
+ class fake_socket:
+ def fileno(self):
+ return 0
+
+ def recv(self, size):
+ raise socket.error(errno.EAGAIN, "EAGAIN")
+
+ class MyChat(asynchat.async_chat):
+ def handle_error(self):
+ raise Exception("error")
+
+ sock = fake_socket()
+ dispatcher = MyChat()
+ dispatcher.set_socket(sock)
+ self.addCleanup(dispatcher.del_channel)
+
+ # must not call handle_error()
+ dispatcher.handle_read()
+
+
class TestHelperFunctions(unittest.TestCase):
def test_find_prefix_at_end(self):
self.assertEqual(asynchat.find_prefix_at_end("qwerty\r", "\r\n"), 1)
@@ -267,6 +296,7 @@
def test_main(verbose=None):
test_support.run_unittest(TestAsynchat, TestAsynchat_WithPoll,
+ TestAsynchatMocked,
TestHelperFunctions, TestFifo)
if __name__ == "__main__":
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@
Library
-------
+- Issue #16133: The asynchat.async_chat.handle_read() method now ignores
+ socket.error() exceptions with blocking I/O errors: EAGAIN, EALREADY,
+ EINPROGRESS, or EWOULDBLOCK.
+
- Issue #1730136: Fix the comparison between a tkFont.Font and an object of
another kind.
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list