Looks like a bug in the `ssl` module, not `asyncio`. Refer to https://github.com/openssl/openssl/issues/710 IMO `ssl` module should be prepared for this.
I'd say post a bug to cpython and see what core devs have to say about it :) Please note exact versions of python and openssl ofc. my 2c: openssl has been a moving target every so often, it's quite possible that this change in the API escaped the devs. On 21 June 2017 at 19:50, Mark E. Haase <meha...@gmail.com> wrote: > (I'm not sure if this is a newbie question or a bug report or something in > between. I apologize in advance if its off-topic. Let me know if I should > post this somewhere else.) > > If a task is cancelled while SSL is being negotiated, then an SSLError is > raised, but there's no way (as far as I can tell) for the caller to catch > it. (The example below is pretty contrived, but in an application I'm > working on, the user can cancel downloads at any time.) Here's an example: > > import asyncio, random, ssl > > async def download(host): > ssl_context = ssl.create_default_context() > reader, writer = await asyncio.open_connection(host, 443, > ssl=ssl_context) > request = f'HEAD / HTTP/1.1\r\nHost: {host}\r\n\r\n' > writer.write(request.encode('ascii')) > lines = list() > while True: > newdata = await reader.readline() > if newdata == b'\r\n': > break > else: > lines.append(newdata.decode('utf8').rstrip('\r\n')) > return lines[0] > > async def main(): > while True: > task = asyncio.Task(download('www.python.org')) > await asyncio.sleep(random.uniform(0.0, 0.5)) > task.cancel() > try: > response = await task > print(response) > except asyncio.CancelledError: > print('request cancelled!') > except ssl.SSLError: > print('caught SSL error') > await asyncio.sleep(1) > > loop = asyncio.get_event_loop() > loop.run_until_complete(main()) > loop.close() > > Running this script yields the following output: > > HTTP/1.1 200 OK > request cancelled! > HTTP/1.1 200 OK > HTTP/1.1 200 OK > <asyncio.sslproto.SSLProtocol object at 0x7fe7c00e5a20>: SSL handshake > failed > Traceback (most recent call last): > File "/usr/lib/python3.6/asyncio/base_events.py", line 803, in > _create_connection_transport > yield from waiter > File "/usr/lib/python3.6/asyncio/tasks.py", line 304, in _wakeup > future.result() > concurrent.futures._base.CancelledError > > During handling of the above exception, another exception occurred: > > Traceback (most recent call last): > File "/usr/lib/python3.6/asyncio/sslproto.py", line 577, in > _on_handshake_complete > raise handshake_exc > File "/usr/lib/python3.6/asyncio/sslproto.py", line 638, in > _process_write_backlog > ssldata = self._sslpipe.shutdown(self._finalize) > File "/usr/lib/python3.6/asyncio/sslproto.py", line 155, in shutdown > ssldata, appdata = self.feed_ssldata(b'') > File "/usr/lib/python3.6/asyncio/sslproto.py", line 219, in > feed_ssldata > self._sslobj.unwrap() > File "/usr/lib/python3.6/ssl.py", line 692, in unwrap > return self._sslobj.shutdown() > ssl.SSLError: [SSL] shutdown while in init (_ssl.c:2299) > > Is this a bug that I should file, or is there some reason that it's intended > to work this way? I can work around it with asyncio.shield(), but I think I > would prefer for the asyncio/sslproto.py to catch the SSLError and ignore > it. Maybe I'm being short sighted. > > Thanks, > Mark > > _______________________________________________ > Async-sig mailing list > Async-sig@python.org > https://mail.python.org/mailman/listinfo/async-sig > Code of Conduct: https://www.python.org/psf/codeofconduct/ > _______________________________________________ Async-sig mailing list Async-sig@python.org https://mail.python.org/mailman/listinfo/async-sig Code of Conduct: https://www.python.org/psf/codeofconduct/