Can you help me understand why _SelectorTransport.__del__()
is called before _SSLProtocolTransport.__del__()?


nottheoilrig@debian:~$ cat script.py
import asyncio

asyncio.get_event_loop().run_until_complete(asyncio.open_connection('google.com', 'https', ssl=True))
nottheoilrig@debian:~$ python3 script.py
Fatal write error on socket transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7fbeb1975c50>
transport: <_SelectorSocketTransport fd=6>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/selector_events.py", line 700, in write
    n = self._sock.send(data)
OSError: [Errno 9] Bad file descriptor
Exception ignored in: <bound method _SSLProtocolTransport.__del__ of <asyncio.sslproto._SSLProtocolTransport object at 0x7fbeb1975b00>>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/sslproto.py", line 328, in __del__
  File "/usr/lib/python3.5/asyncio/sslproto.py", line 319, in close
File "/usr/lib/python3.5/asyncio/sslproto.py", line 542, in _start_shutdown File "/usr/lib/python3.5/asyncio/sslproto.py", line 547, in _write_appdata File "/usr/lib/python3.5/asyncio/sslproto.py", line 651, in _process_write_backlog
  File "/usr/lib/python3.5/asyncio/sslproto.py", line 658, in _fatal_error
NameError: name 'base_events' is not defined
nottheoilrig@debian:~$


Besides the NameError, _SelectorTransport.__del__()
is called before _SSLProtocolTransport.__del__().
If that's to be expected, I assume you'd expect an error if you closed the underlying socket and then closed the _SSLProtocolTransport:


nottheoilrig@debian:~$ cat script.py
import asyncio

reader, writer = asyncio.get_event_loop().run_until_complete(asyncio.open_connection('google.com', 'https', ssl=True))
writer.transport._ssl_protocol._transport._sock.close()
writer.transport.close()
nottheoilrig@debian:~$ python3 script.py
Fatal write error on socket transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f4830c9cc50>
transport: <_SelectorSocketTransport fd=6 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/selector_events.py", line 700, in write
    n = self._sock.send(data)
OSError: [Errno 9] Bad file descriptor
nottheoilrig@debian:~$


However that's exactly what _SelectorTransport.__del__()
and _SSLProtocolTransport.__del__() do
(commit 241c71030cb79217bd6be6f6dfe31e87bc5f6cbf)

Should _SSLProtocolTransport.__del__() be called before _SelectorTransport.__del__() or should they handle the case that they're called in this order? (without raising a fatal error) Or is a fatal error appropriate? (A ResourceWarning is already emitted if a transport or event loop isn't closed explicitly.)

Reply via email to