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 <mehaase@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/