Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b4bebda

Browse files
committed
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.
1 parent 727a463 commit b4bebda

4 files changed

Lines changed: 54 additions & 13 deletions

File tree

Doc/library/ssl.rst

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,8 +1604,25 @@ the sockets in non-blocking mode and use an event loop).
16041604
Notes on non-blocking sockets
16051605
-----------------------------
16061606

1607-
When working with non-blocking sockets, there are several things you need
1608-
to be aware of:
1607+
SSL sockets behave slightly different than regular sockets in
1608+
non-blocking mode. When working with non-blocking sockets, there are
1609+
thus several things you need to be aware of:
1610+
1611+
- Most :class:`SSLSocket` methods will raise either
1612+
:exc:`SSLWantWriteError` or :exc:`SSLWantReadError` instead of
1613+
:exc:`BlockingIOError` if an I/O operation would
1614+
block. :exc:`SSLWantReadError` will be raised if a read operation on
1615+
the underlying socket is necessary, and :exc:`SSLWantWriteError` for
1616+
a write operation on the underlying socket. Note that attempts to
1617+
*write* to an SSL socket may require *reading* from the underlying
1618+
socket first, and attempts to *read* from the SSL socket may require
1619+
a prior *write* to the underlying socket.
1620+
1621+
.. versionchanged:: 3.5
1622+
1623+
In earlier Python versions, the :meth:`!SSLSocket.send` method
1624+
returned zero instead of raising :exc:`SSLWantWriteError` or
1625+
:exc:`SSLWantReadError`.
16091626

16101627
- Calling :func:`~select.select` tells you that the OS-level socket can be
16111628
read from (or written to), but it does not imply that there is sufficient

Lib/ssl.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -664,17 +664,7 @@ def send(self, data, flags=0):
664664
raise ValueError(
665665
"non-zero flags not allowed in calls to send() on %s" %
666666
self.__class__)
667-
try:
668-
v = self._sslobj.write(data)
669-
except SSLError as x:
670-
if x.args[0] == SSL_ERROR_WANT_READ:
671-
return 0
672-
elif x.args[0] == SSL_ERROR_WANT_WRITE:
673-
return 0
674-
else:
675-
raise
676-
else:
677-
return v
667+
return self._sslobj.write(data)
678668
else:
679669
return socket.send(self, data, flags)
680670

Lib/test/test_ssl.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,36 @@ def _recvfrom_into():
25472547
s.write(b"over\n")
25482548
s.close()
25492549

2550+
def test_nonblocking_send(self):
2551+
server = ThreadedEchoServer(CERTFILE,
2552+
certreqs=ssl.CERT_NONE,
2553+
ssl_version=ssl.PROTOCOL_TLSv1,
2554+
cacerts=CERTFILE,
2555+
chatty=True,
2556+
connectionchatty=False)
2557+
with server:
2558+
s = ssl.wrap_socket(socket.socket(),
2559+
server_side=False,
2560+
certfile=CERTFILE,
2561+
ca_certs=CERTFILE,
2562+
cert_reqs=ssl.CERT_NONE,
2563+
ssl_version=ssl.PROTOCOL_TLSv1)
2564+
s.connect((HOST, server.port))
2565+
s.setblocking(False)
2566+
2567+
# If we keep sending data, at some point the buffers
2568+
# will be full and the call will block
2569+
buf = bytearray(8192)
2570+
def fill_buffer():
2571+
while True:
2572+
s.send(buf)
2573+
self.assertRaises((ssl.SSLWantWriteError,
2574+
ssl.SSLWantReadError), fill_buffer)
2575+
2576+
# Now read all the output and discard it
2577+
s.setblocking(True)
2578+
s.close()
2579+
25502580
def test_handshake_timeout(self):
25512581
# Issue #5103: SSL handshake must respect the socket timeout
25522582
server = socket.socket(socket.AF_INET)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ Core and Builtins
6060
Library
6161
-------
6262

63+
- Issue #20951: SSLSocket.send() now raises either SSLWantReadError or
64+
SSLWantWriteError on a non-blocking socket if the operation would block.
65+
Previously, it would return 0. Patch by Nikolaus Rath.
66+
6367
- Issue #13248: removed previously deprecated asyncore.dispatcher __getattr__
6468
cheap inheritance hack.
6569

0 commit comments

Comments
 (0)