summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-07-29 21:09:56 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-07-29 21:09:56 (GMT)
commit66565649b53b39a11306d96935be8a4810a70f3f (patch)
tree852dc7f6f6272a6cfb1433a3067dac569adb3d08
parentacc6e7596f515c2e0a3376a5ef647f531f22a824 (diff)
parent9c9f1f10d391ff3458a80fc3d0110870d50012e2 (diff)
downloadcpython-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.py8
-rw-r--r--Lib/asyncio/selector_events.py8
-rw-r--r--Lib/asyncio/unix_events.py14
-rw-r--r--Lib/test/test_asyncio/test_events.py18
-rw-r--r--Lib/test/test_asyncio/test_unix_events.py4
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)