Description
Bug report
Bug description:
There are several pathways to this bug, all which call asyncio.sslproto._SSLProtocolTransport._force_close()
with an exception instance:
- During shutdown, if the flushing state takes too long (
asyncio.sslproto.SSLProtocolTransport._check_shutdown_timeout()
is called) - Anything that triggers a call to
asyncio.sslproto.SSLProtocol._fatal_error()
, e.g. SSL handshake timeout or exception, SSL shutdown timeout or exception, an exception during reading, exception raised in the app transport EOF handler, etc.
I'm seeing this when using a HTTPS proxy with a aiohttp client session (which wraps TLS in TLS), but I don't think it is specific to that context. I'm seeing these tracebacks:
Fatal error on SSL protocol
protocol: <asyncio.sslproto.SSLProtocol object at 0x7fe36f3a1350>
transport: <_SelectorSocketTransport closing fd=6 read=idle write=<idle, bufsize=0>>
Traceback (most recent call last):
File ".../lib/python3.11/asyncio/sslproto.py", line 644, in _do_shutdown
self._sslobj.unwrap()
File ".../lib/python3.11/ssl.py", line 983, in unwrap
return self._sslobj.shutdown()
^^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2702)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".../lib/python3.11/asyncio/sslproto.py", line 731, in _do_read
self._do_read__buffered()
File ".../lib/python3.11/asyncio/sslproto.py", line 765, in _do_read__buffered
self._app_protocol_buffer_updated(offset)
File ".../lib/python3.11/asyncio/sslproto.py", line 445, in buffer_updated
self._do_shutdown()
File ".../lib/python3.11/asyncio/sslproto.py", line 648, in _do_shutdown
self._on_shutdown_complete(exc)
File ".../lib/python3.11/asyncio/sslproto.py", line 660, in _on_shutdown_complete
self._fatal_error(shutdown_exc)
File ".../lib/python3.11/asyncio/sslproto.py", line 911, in _fatal_error
self._transport._force_close(exc)
File ".../lib/python3.11/asyncio/sslproto.py", line 252, in _force_close
self._ssl_protocol._abort(exc)
TypeError: SSLProtocol._abort() takes 1 positional argument but 2 were given
To me, the implementation of _SSLProtocolTransport._force_close()
looks like an unfinished copy of the _SSLProtocolTransport.abort()
method:
cpython/Lib/asyncio/sslproto.py
Lines 239 to 252 in 1583c40
At any rate, the self._ssl_protocol
attribute is an instance of SSLProtocol
in the same module, and the _abort()
method on that class doesn't accept an exception instance:
cpython/Lib/asyncio/sslproto.py
Lines 664 to 667 in 1583c40
I find the test suite surrounding the SSL protocol to be dense enough that I can't easily spot how to provide an update there to reproduce this issue more easily, but the fix looks simple enough: don't pass an argument to _abort()
.
CPython versions tested on:
3.11, 3.12, CPython main branch
Operating systems tested on:
Linux
Linked PRs
Metadata
Metadata
Assignees
Projects
Status