diff options
| author | Victor Stinner <victor.stinner@gmail.com> | 2014-07-29 21:09:56 (GMT) |
|---|---|---|
| committer | Victor Stinner <victor.stinner@gmail.com> | 2014-07-29 21:09:56 (GMT) |
| commit | 66565649b53b39a11306d96935be8a4810a70f3f (patch) | |
| tree | 852dc7f6f6272a6cfb1433a3067dac569adb3d08 | |
| parent | acc6e7596f515c2e0a3376a5ef647f531f22a824 (diff) | |
| parent | 9c9f1f10d391ff3458a80fc3d0110870d50012e2 (diff) | |
| download | cpython-66565649b53b39a11306d96935be8a4810a70f3f.zip cpython-66565649b53b39a11306d96935be8a4810a70f3f.tar.gz cpython-66565649b53b39a11306d96935be8a4810a70f3f.tar.bz2 | |
Merge with Python 3.4 (asyncio)
- Close #22063: socket operations (socket,recv, sock_sendall, sock_connect,
sock_accept) now raise an exception in debug mode if sockets are in blocking
mode.
- asyncio: Use the new os.set_blocking() function of Python 3.5 if available
| -rw-r--r-- | Lib/asyncio/proactor_events.py | 8 | ||||
| -rw-r--r-- | Lib/asyncio/selector_events.py | 8 | ||||
| -rw-r--r-- | Lib/asyncio/unix_events.py | 14 | ||||
| -rw-r--r-- | Lib/test/test_asyncio/test_events.py | 18 | ||||
| -rw-r--r-- | Lib/test/test_asyncio/test_unix_events.py | 4 |
5 files changed, 48 insertions, 4 deletions
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index ab566b3..751155b 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -385,12 +385,18 @@ class BaseProactorEventLoop(base_events.BaseEventLoop): self._selector = None def sock_recv(self, sock, n): + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") return self._proactor.recv(sock, n) def sock_sendall(self, sock, data): + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") return self._proactor.send(sock, data) def sock_connect(self, sock, address): + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") try: base_events._check_resolved_address(sock, address) except ValueError as err: @@ -401,6 +407,8 @@ class BaseProactorEventLoop(base_events.BaseEventLoop): return self._proactor.connect(sock, address) def sock_accept(self, sock): + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") return self._proactor.accept(sock) def _socketpair(self): diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index eca48b8..6b7bdf0 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -256,6 +256,8 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): This method is a coroutine. """ + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") fut = futures.Future(loop=self) self._sock_recv(fut, False, sock, n) return fut @@ -292,6 +294,8 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): This method is a coroutine. """ + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") fut = futures.Future(loop=self) if data: self._sock_sendall(fut, False, sock, data) @@ -333,6 +337,8 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): This method is a coroutine. """ + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") fut = futures.Future(loop=self) try: base_events._check_resolved_address(sock, address) @@ -374,6 +380,8 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): This method is a coroutine. """ + if self.get_debug() and sock.gettimeout() != 0: + raise ValueError("the socket must be non-blocking") fut = futures.Future(loop=self) self._sock_accept(fut, False, sock) return fut diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 665901a..94a46d0 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -258,6 +258,16 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): return server +if hasattr(os, 'set_blocking'): + def _set_nonblocking(fd): + os.set_blocking(fd, False) +else: + def _set_nonblocking(fd): + flags = fcntl.fcntl(fd, fcntl.F_GETFL) + flags = flags | os.O_NONBLOCK + fcntl.fcntl(fd, fcntl.F_SETFL, flags) + + class _UnixReadPipeTransport(transports.ReadTransport): max_size = 256 * 1024 # max bytes we read in one event loop iteration @@ -273,7 +283,7 @@ class _UnixReadPipeTransport(transports.ReadTransport): stat.S_ISSOCK(mode) or stat.S_ISCHR(mode)): raise ValueError("Pipe transport is for pipes/sockets only.") - os.set_blocking(self._fileno, False) + _set_nonblocking(self._fileno) self._protocol = protocol self._closing = False self._loop.add_reader(self._fileno, self._read_ready) @@ -366,7 +376,7 @@ class _UnixWritePipeTransport(transports._FlowControlMixin, stat.S_ISCHR(mode)): raise ValueError("Pipe transport is only for " "pipes, sockets and character devices") - os.set_blocking(self._fileno, False) + _set_nonblocking(self._fileno) self._protocol = protocol self._buffer = [] self._conn_lost = 0 diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index cce6467..f6220f4 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -383,6 +383,24 @@ class EventLoopTestsMixin: self.assertEqual(read, data) def _basetest_sock_client_ops(self, httpd, sock): + # in debug mode, socket operations must fail + # if the socket is not in blocking mode + self.loop.set_debug(True) + sock.setblocking(True) + with self.assertRaises(ValueError): + self.loop.run_until_complete( + self.loop.sock_connect(sock, httpd.address)) + with self.assertRaises(ValueError): + self.loop.run_until_complete( + self.loop.sock_sendall(sock, b'GET / HTTP/1.0\r\n\r\n')) + with self.assertRaises(ValueError): + self.loop.run_until_complete( + self.loop.sock_recv(sock, 1024)) + with self.assertRaises(ValueError): + self.loop.run_until_complete( + self.loop.sock_accept(sock)) + + # test in non-blocking mode sock.setblocking(False) self.loop.run_until_complete( self.loop.sock_connect(sock, httpd.address)) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index d185533..e397598 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -306,7 +306,7 @@ class UnixReadPipeTransportTests(test_utils.TestCase): self.pipe = mock.Mock(spec_set=io.RawIOBase) self.pipe.fileno.return_value = 5 - blocking_patcher = mock.patch('os.set_blocking') + blocking_patcher = mock.patch('asyncio.unix_events._set_nonblocking') blocking_patcher.start() self.addCleanup(blocking_patcher.stop) @@ -469,7 +469,7 @@ class UnixWritePipeTransportTests(test_utils.TestCase): self.pipe = mock.Mock(spec_set=io.RawIOBase) self.pipe.fileno.return_value = 5 - blocking_patcher = mock.patch('os.set_blocking') + blocking_patcher = mock.patch('asyncio.unix_events._set_nonblocking') blocking_patcher.start() self.addCleanup(blocking_patcher.stop) |
