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.
+
Usage::
with support.catch_unraisable_exception() as cm:
"""
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.
+
Usage:
with support.catch_unraisable_exception() as cm:
self._old_hook = None
def _hook(self, unraisable):
+ # Storing unraisable.object can resurrect an object which is being
+ # finalized. Storing unraisable.exc_value creates a reference cycle.
self.unraisable = unraisable
def __enter__(self):
return self
def __exit__(self, *exc_info):
- # Clear the unraisable exception to explicitly break a reference cycle
- del self.unraisable
+ # 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