<div dir="ltr">(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.)<div><br></div><div><div>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:</div></div><div><div><br></div><div><div>    import asyncio, random, ssl</div><div><br></div><div>    async def download(host):</div><div>        ssl_context = ssl.create_default_context()</div><div>        reader, writer = await asyncio.open_connection(host, 443, ssl=ssl_context)</div><div>        request = f'HEAD / HTTP/1.1\r\nHost: {host}\r\n\r\n'</div><div>        writer.write(request.encode('ascii'))</div><div>        lines = list()</div><div>        while True:</div><div>            newdata = await reader.readline()</div><div>            if newdata == b'\r\n':</div><div>                break</div><div>            else:</div><div>                lines.append(newdata.decode('utf8').rstrip('\r\n'))</div><div>        return lines[0]</div><div><br></div><div>    async def main():</div><div>        while True:</div><div>            task = asyncio.Task(download('<a href="http://www.python.org">www.python.org</a>'))</div><div>            await asyncio.sleep(random.uniform(0.0, 0.5))</div><div>            task.cancel()</div><div>            try:</div><div>                response = await task</div><div>                print(response)</div><div>            except asyncio.CancelledError:</div><div>                print('request cancelled!')</div><div><div>            except ssl.SSLError:</div><div>                print('caught SSL error')</div></div><div>            await asyncio.sleep(1)<br></div><div><br></div><div>    loop = asyncio.get_event_loop()</div><div>    loop.run_until_complete(main())</div><div>    loop.close()</div></div><div><br></div><div>Running this script yields the following output:</div><div><br></div><div><div>    HTTP/1.1 200 OK</div><div>    request cancelled!</div><div>    HTTP/1.1 200 OK</div><div>    HTTP/1.1 200 OK</div><div>    <asyncio.sslproto.SSLProtocol object at 0x7fe7c00e5a20>: SSL handshake failed</div><div>    Traceback (most recent call last):</div><div>      File "/usr/lib/python3.6/asyncio/base_events.py", line 803, in _create_connection_transport</div><div>        yield from waiter</div><div>      File "/usr/lib/python3.6/asyncio/tasks.py", line 304, in _wakeup</div><div>        future.result()</div><div>    concurrent.futures._base.CancelledError</div><div><br></div><div>    During handling of the above exception, another exception occurred:</div><div><br></div><div>    Traceback (most recent call last):</div><div>      File "/usr/lib/python3.6/asyncio/sslproto.py", line 577, in _on_handshake_complete</div><div>        raise handshake_exc</div><div>      File "/usr/lib/python3.6/asyncio/sslproto.py", line 638, in _process_write_backlog</div><div>        ssldata = self._sslpipe.shutdown(self._finalize)</div><div>      File "/usr/lib/python3.6/asyncio/sslproto.py", line 155, in shutdown</div><div>        ssldata, appdata = self.feed_ssldata(b'')</div><div>      File "/usr/lib/python3.6/asyncio/sslproto.py", line 219, in feed_ssldata</div><div>        self._sslobj.unwrap()</div><div>      File "/usr/lib/python3.6/ssl.py", line 692, in unwrap</div><div>        return self._sslobj.shutdown()</div><div>    ssl.SSLError: [SSL] shutdown while in init (_ssl.c:2299)</div></div></div><div><br></div><div>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.<br></div><div><br></div><div>Thanks,</div><div>Mark</div></div>