diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/asynchat.py | 9 | ||||
-rw-r--r-- | Lib/test/test_asynchat.py | 32 |
2 files changed, 39 insertions, 2 deletions
diff --git a/Lib/asynchat.py b/Lib/asynchat.py index 911833d..57459a0 100644 --- a/Lib/asynchat.py +++ b/Lib/asynchat.py @@ -46,12 +46,17 @@ method) up to the terminator, and then control will be returned to you - by calling your self.found_terminator() method. """ -import socket import asyncore +import errno +import socket 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 @@ class async_chat (asyncore.dispatcher): 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 index c81ec0d..9c4c714 100644 --- 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(unittest.TestCase): 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 @@ class TestFifo(unittest.TestCase): def test_main(verbose=None): test_support.run_unittest(TestAsynchat, TestAsynchat_WithPoll, + TestAsynchatMocked, TestHelperFunctions, TestFifo) if __name__ == "__main__": |