Commit fb2c3465 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

asyncio: __del__() keep reference to warnings.warn (GH-11491)

* asyncio: __del__() keep reference to warnings.warn

The __del__() methods of asyncio classes now keep a strong reference
to the warnings.warn() to be able to display the ResourceWarning
warning in more cases. Ensure that the function remains available if
instances are destroyed late during Python shutdown (while module
symbols are cleared).

* Rename warn parameter to _warn

"_warn" name is a hint that it's not the regular warnings.warn()
function.
parent 9b07681c
...@@ -622,10 +622,9 @@ class BaseEventLoop(events.AbstractEventLoop): ...@@ -622,10 +622,9 @@ class BaseEventLoop(events.AbstractEventLoop):
"""Returns True if the event loop was closed.""" """Returns True if the event loop was closed."""
return self._closed return self._closed
def __del__(self): def __del__(self, _warn=warnings.warn):
if not self.is_closed(): if not self.is_closed():
warnings.warn(f"unclosed event loop {self!r}", ResourceWarning, _warn(f"unclosed event loop {self!r}", ResourceWarning, source=self)
source=self)
if not self.is_running(): if not self.is_running():
self.close() self.close()
......
...@@ -120,10 +120,9 @@ class BaseSubprocessTransport(transports.SubprocessTransport): ...@@ -120,10 +120,9 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
# Don't clear the _proc reference yet: _post_init() may still run # Don't clear the _proc reference yet: _post_init() may still run
def __del__(self): def __del__(self, _warn=warnings.warn):
if not self._closed: if not self._closed:
warnings.warn(f"unclosed transport {self!r}", ResourceWarning, _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
source=self)
self.close() self.close()
def get_pid(self): def get_pid(self):
......
...@@ -89,10 +89,9 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin, ...@@ -89,10 +89,9 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin,
self._read_fut.cancel() self._read_fut.cancel()
self._read_fut = None self._read_fut = None
def __del__(self): def __del__(self, _warn=warnings.warn):
if self._sock is not None: if self._sock is not None:
warnings.warn(f"unclosed transport {self!r}", ResourceWarning, _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
source=self)
self.close() self.close()
def _fatal_error(self, exc, message='Fatal error on pipe transport'): def _fatal_error(self, exc, message='Fatal error on pipe transport'):
......
...@@ -658,10 +658,9 @@ class _SelectorTransport(transports._FlowControlMixin, ...@@ -658,10 +658,9 @@ class _SelectorTransport(transports._FlowControlMixin,
self._loop._remove_writer(self._sock_fd) self._loop._remove_writer(self._sock_fd)
self._loop.call_soon(self._call_connection_lost, None) self._loop.call_soon(self._call_connection_lost, None)
def __del__(self): def __del__(self, _warn=warnings.warn):
if self._sock is not None: if self._sock is not None:
warnings.warn(f"unclosed transport {self!r}", ResourceWarning, _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
source=self)
self._sock.close() self._sock.close()
def _fatal_error(self, exc, message='Fatal error on transport'): def _fatal_error(self, exc, message='Fatal error on transport'):
......
...@@ -316,10 +316,9 @@ class _SSLProtocolTransport(transports._FlowControlMixin, ...@@ -316,10 +316,9 @@ class _SSLProtocolTransport(transports._FlowControlMixin,
self._closed = True self._closed = True
self._ssl_protocol._start_shutdown() self._ssl_protocol._start_shutdown()
def __del__(self): def __del__(self, _warn=warnings.warn):
if not self._closed: if not self._closed:
warnings.warn(f"unclosed transport {self!r}", ResourceWarning, _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
source=self)
self.close() self.close()
def is_reading(self): def is_reading(self):
......
...@@ -511,10 +511,9 @@ class _UnixReadPipeTransport(transports.ReadTransport): ...@@ -511,10 +511,9 @@ class _UnixReadPipeTransport(transports.ReadTransport):
if not self._closing: if not self._closing:
self._close(None) self._close(None)
def __del__(self): def __del__(self, _warn=warnings.warn):
if self._pipe is not None: if self._pipe is not None:
warnings.warn(f"unclosed transport {self!r}", ResourceWarning, _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
source=self)
self._pipe.close() self._pipe.close()
def _fatal_error(self, exc, message='Fatal error on pipe transport'): def _fatal_error(self, exc, message='Fatal error on pipe transport'):
...@@ -707,10 +706,9 @@ class _UnixWritePipeTransport(transports._FlowControlMixin, ...@@ -707,10 +706,9 @@ class _UnixWritePipeTransport(transports._FlowControlMixin,
# write_eof is all what we needed to close the write pipe # write_eof is all what we needed to close the write pipe
self.write_eof() self.write_eof()
def __del__(self): def __del__(self, _warn=warnings.warn):
if self._pipe is not None: if self._pipe is not None:
warnings.warn(f"unclosed transport {self!r}", ResourceWarning, _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
source=self)
self._pipe.close() self._pipe.close()
def abort(self): def abort(self):
......
...@@ -107,10 +107,9 @@ class PipeHandle: ...@@ -107,10 +107,9 @@ class PipeHandle:
CloseHandle(self._handle) CloseHandle(self._handle)
self._handle = None self._handle = None
def __del__(self): def __del__(self, _warn=warnings.warn):
if self._handle is not None: if self._handle is not None:
warnings.warn(f"unclosed {self!r}", ResourceWarning, _warn(f"unclosed {self!r}", ResourceWarning, source=self)
source=self)
self.close() self.close()
def __enter__(self): def __enter__(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment