SSL hangs if connection is closed before handshake completed
tvoinarovskyi opened this issue · 5 comments
Here's the snippet, that replicates the issue. I stomped upon this in normal TCP sockets, so sockpair is not the issue.
import asyncio
import socket
import ssl
import sys
import threading
context = ssl.create_default_context()
rsock, wsock = socket.socketpair()
def reader(sock):
data = sock.recv(4)
print("RCV", data)
sock.close()
t = threading.Thread(target=reader, args=(rsock, ))
t.start()
try:
if sys.argv[1] == 'sync':
# The blocking example works OK. Exits right away
sock = context.wrap_socket(
wsock,
server_hostname="localhost",
)
print("Connected")
elif sys.argv[1] == "async":
# Non blocking call example
async def connect(loop):
reader, writer = await asyncio.open_connection(
sock=wsock, ssl=context, loop=loop,
server_hostname="localhost")
print("Connected Async")
loop = asyncio.get_event_loop()
loop.run_until_complete(loop.create_task(connect(loop)))
finally:
wsock.close()
t.join()
The idea is, that the other end is not an SSL socket, but rather some plain protocol, that reads size (lets say 4 bytes) and closes the socket, as size is inappropriate.
Blocking (test.py sync
) socket works as expected raising ConnectionResetError
Async (test.py async
) example blocks forever
Version:
Python 3.5.2 (default, Jul 17 2016, 00:00:00)
[GCC 4.8.4] on linux
Tried with uvloop, it does not support sockpair, as it's not AF_INET, so the example does not work there. Tried it on a normal TCP, and it also hangs.
uvloop==0.6.5
Thanks for reporting this. I'll take a look.
Tried with uvloop, it does not support sockpair, as it's not AF_INET, so the example does not work
It's because create_connection
didn't support AF_UNIX
sockets. It's fixed in the master
branch now.
Tried it on a normal TCP, and it also hangs.
uvloop uses asyncio/sslproto.py
and the bug is probably there.
Bug is in function connection_lost
(member function of class SSLProtocol
in asyncio/sslproto.py
). This function should call _wakeup_waiter
otherwise function _create_connection_transport
(in asyncio/base_events.py
) will hang on yield from waiter
.
@HoHo-Ho Would you be able to write a patch+test for this and submit to http://github.com/python/asyncio asap? Python 3.6 is scheduled to be released tomorrow, we might still have time to fix this.
Closing this issue now.