[Python-checkins] cpython: Issue #20951: SSLSocket.send() now raises either SSLWantReadError or
antoine.pitrou
python-checkins at python.org
Tue Apr 29 10:03:37 CEST 2014
http://hg.python.org/cpython/rev/3cf067049211
changeset: 90506:3cf067049211
user: Antoine Pitrou <solipsis at pitrou.net>
date: Tue Apr 29 10:03:28 2014 +0200
summary:
Issue #20951: SSLSocket.send() now raises either SSLWantReadError or SSLWantWriteError on a non-blocking socket if the operation would block. Previously, it would return 0.
Patch by Nikolaus Rath.
files:
Doc/library/ssl.rst | 21 +++++++++++++++++++--
Lib/ssl.py | 12 +-----------
Lib/test/test_ssl.py | 30 ++++++++++++++++++++++++++++++
Misc/NEWS | 4 ++++
4 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -1604,8 +1604,25 @@
Notes on non-blocking sockets
-----------------------------
-When working with non-blocking sockets, there are several things you need
-to be aware of:
+SSL sockets behave slightly different than regular sockets in
+non-blocking mode. When working with non-blocking sockets, there are
+thus several things you need to be aware of:
+
+- Most :class:`SSLSocket` methods will raise either
+ :exc:`SSLWantWriteError` or :exc:`SSLWantReadError` instead of
+ :exc:`BlockingIOError` if an I/O operation would
+ block. :exc:`SSLWantReadError` will be raised if a read operation on
+ the underlying socket is necessary, and :exc:`SSLWantWriteError` for
+ a write operation on the underlying socket. Note that attempts to
+ *write* to an SSL socket may require *reading* from the underlying
+ socket first, and attempts to *read* from the SSL socket may require
+ a prior *write* to the underlying socket.
+
+ .. versionchanged:: 3.5
+
+ In earlier Python versions, the :meth:`!SSLSocket.send` method
+ returned zero instead of raising :exc:`SSLWantWriteError` or
+ :exc:`SSLWantReadError`.
- Calling :func:`~select.select` tells you that the OS-level socket can be
read from (or written to), but it does not imply that there is sufficient
diff --git a/Lib/ssl.py b/Lib/ssl.py
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -664,17 +664,7 @@
raise ValueError(
"non-zero flags not allowed in calls to send() on %s" %
self.__class__)
- try:
- v = self._sslobj.write(data)
- except SSLError as x:
- if x.args[0] == SSL_ERROR_WANT_READ:
- return 0
- elif x.args[0] == SSL_ERROR_WANT_WRITE:
- return 0
- else:
- raise
- else:
- return v
+ return self._sslobj.write(data)
else:
return socket.send(self, data, flags)
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -2547,6 +2547,36 @@
s.write(b"over\n")
s.close()
+ def test_nonblocking_send(self):
+ server = ThreadedEchoServer(CERTFILE,
+ certreqs=ssl.CERT_NONE,
+ ssl_version=ssl.PROTOCOL_TLSv1,
+ cacerts=CERTFILE,
+ chatty=True,
+ connectionchatty=False)
+ with server:
+ s = ssl.wrap_socket(socket.socket(),
+ server_side=False,
+ certfile=CERTFILE,
+ ca_certs=CERTFILE,
+ cert_reqs=ssl.CERT_NONE,
+ ssl_version=ssl.PROTOCOL_TLSv1)
+ s.connect((HOST, server.port))
+ s.setblocking(False)
+
+ # If we keep sending data, at some point the buffers
+ # will be full and the call will block
+ buf = bytearray(8192)
+ def fill_buffer():
+ while True:
+ s.send(buf)
+ self.assertRaises((ssl.SSLWantWriteError,
+ ssl.SSLWantReadError), fill_buffer)
+
+ # Now read all the output and discard it
+ s.setblocking(True)
+ s.close()
+
def test_handshake_timeout(self):
# Issue #5103: SSL handshake must respect the socket timeout
server = socket.socket(socket.AF_INET)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -60,6 +60,10 @@
Library
-------
+- Issue #20951: SSLSocket.send() now raises either SSLWantReadError or
+ SSLWantWriteError on a non-blocking socket if the operation would block.
+ Previously, it would return 0. Patch by Nikolaus Rath.
+
- Issue #13248: removed previously deprecated asyncore.dispatcher __getattr__
cheap inheritance hack.
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list