mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
bpo-37261: Document sys.unraisablehook corner cases (GH-14059)
Document reference cycle and resurrected objects issues in sys.unraisablehook() and threading.excepthook() documentation. Fix test.support.catch_unraisable_exception(): __exit__() no longer ignores unraisable exceptions. Fix test_io test_writer_close_error_on_close(): use a second catch_unraisable_exception() to catch the BufferedWriter unraisable exception.
This commit is contained in:
parent
9765efcb39
commit
212646cae6
5 changed files with 30 additions and 23 deletions
|
@ -1514,13 +1514,21 @@ always available.
|
|||
* *err_msg*: Error message, can be ``None``.
|
||||
* *object*: Object causing the exception, can be ``None``.
|
||||
|
||||
:func:`sys.unraisablehook` can be overridden to control how unraisable
|
||||
exceptions are handled.
|
||||
|
||||
The default hook formats *err_msg* and *object* as:
|
||||
``f'{err_msg}: {object!r}'``; use "Exception ignored in" error message
|
||||
if *err_msg* is ``None``.
|
||||
|
||||
:func:`sys.unraisablehook` can be overridden to control how unraisable
|
||||
exceptions are handled.
|
||||
|
||||
Storing *exc_value* using a custom hook can create a reference cycle. It
|
||||
should be cleared explicitly to break the reference cycle when the
|
||||
exception is no longer needed.
|
||||
|
||||
Storing *object* using a custom hook can resurrect it if it is set to an
|
||||
object which is being finalized. Avoid storing *object* after the custom
|
||||
hook completes to avoid resurrecting objects.
|
||||
|
||||
See also :func:`excepthook` which handles uncaught exceptions.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
|
|
@ -1086,17 +1086,13 @@ The :mod:`test.support` module defines the following functions:
|
|||
Context manager catching unraisable exception using
|
||||
:func:`sys.unraisablehook`.
|
||||
|
||||
If the *object* attribute of the unraisable hook is set and the object is
|
||||
being finalized, the object is resurrected because the context manager
|
||||
stores a strong reference to it (``cm.unraisable.object``).
|
||||
|
||||
Storing the exception value (``cm.unraisable.exc_value``) creates a
|
||||
reference cycle. The reference cycle is broken explicitly when the context
|
||||
manager exits.
|
||||
|
||||
Exiting the context manager clears the stored unraisable exception. It can
|
||||
trigger a new unraisable exception (ex: the resurrected object is finalized
|
||||
again and raises the same exception): it is silently ignored in this case.
|
||||
Storing the object (``cm.unraisable.object``) can resurrect it if it is set
|
||||
to an object which is being finalized. Exiting the context manager clears
|
||||
the stored object.
|
||||
|
||||
Usage::
|
||||
|
||||
|
|
|
@ -58,6 +58,14 @@ This module defines the following functions:
|
|||
:func:`threading.excepthook` can be overridden to control how uncaught
|
||||
exceptions raised by :func:`Thread.run` are handled.
|
||||
|
||||
Storing *exc_value* using a custom hook can create a reference cycle. It
|
||||
should be cleared explicitly to break the reference cycle when the
|
||||
exception is no longer needed.
|
||||
|
||||
Storing *object* using a custom hook can resurrect it if it is set to an
|
||||
object which is being finalized. Avoid storing *object* after the custom
|
||||
hook completes to avoid resurrecting objects.
|
||||
|
||||
.. seealso::
|
||||
:func:`sys.excepthook` handles uncaught exceptions.
|
||||
|
||||
|
|
|
@ -3040,17 +3040,13 @@ class catch_unraisable_exception:
|
|||
"""
|
||||
Context manager catching unraisable exception using sys.unraisablehook.
|
||||
|
||||
If the *object* attribute of the unraisable hook is set and the object is
|
||||
being finalized, the object is resurrected because the context manager
|
||||
stores a strong reference to it (cm.unraisable.object).
|
||||
|
||||
Storing the exception value (cm.unraisable.exc_value) creates a reference
|
||||
cycle. The reference cycle is broken explicitly when the context manager
|
||||
exits.
|
||||
|
||||
Exiting the context manager clears the stored unraisable exception. It can
|
||||
trigger a new unraisable exception (ex: the resurrected object is finalized
|
||||
again and raises the same exception): it is silently ignored in this case.
|
||||
Storing the object (cm.unraisable.object) can resurrect it if it is set to
|
||||
an object which is being finalized. Exiting the context manager clears the
|
||||
stored object.
|
||||
|
||||
Usage:
|
||||
|
||||
|
@ -3080,10 +3076,5 @@ class catch_unraisable_exception:
|
|||
return self
|
||||
|
||||
def __exit__(self, *exc_info):
|
||||
# Clear the unraisable exception to explicitly break a reference cycle.
|
||||
# It can call _hook() again: ignore the new unraisable exception in
|
||||
# this case.
|
||||
self.unraisable = None
|
||||
|
||||
sys.unraisablehook = self._old_hook
|
||||
del self.unraisable
|
||||
|
|
|
@ -2072,8 +2072,12 @@ class BufferedRWPairTest(unittest.TestCase):
|
|||
writer.close = lambda: None
|
||||
writer = None
|
||||
|
||||
# Ignore BufferedWriter (of the BufferedRWPair) unraisable exception
|
||||
with support.catch_unraisable_exception():
|
||||
pair = None
|
||||
# Ignore BufferedRWPair unraisable exception
|
||||
with support.catch_unraisable_exception():
|
||||
pair = None
|
||||
support.gc_collect()
|
||||
support.gc_collect()
|
||||
|
||||
def test_reader_writer_close_error_on_close(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue