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:
|
def abort(self): |
|
"""Close the transport immediately. |
|
|
|
Buffered data will be lost. No more data will be received. |
|
The protocol's connection_lost() method will (eventually) be |
|
called with None as its argument. |
|
""" |
|
self._closed = True |
|
if self._ssl_protocol is not None: |
|
self._ssl_protocol._abort() |
|
|
|
def _force_close(self, exc): |
|
self._closed = True |
|
self._ssl_protocol._abort(exc) |
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:
|
def _abort(self): |
|
self._set_state(SSLProtocolState.UNWRAPPED) |
|
if self._transport is not None: |
|
self._transport.abort() |
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
Bug report
Bug description:
There are several pathways to this bug, all which call
asyncio.sslproto._SSLProtocolTransport._force_close()with an exception instance:asyncio.sslproto.SSLProtocolTransport._check_shutdown_timeout()is called)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:
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_protocolattribute is an instance ofSSLProtocolin 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