diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-06-13 12:44:54 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-13 12:44:54 (GMT) |
commit | 6d22cc8e90ccb1e1965b1a4bc79456e2cc1e5a3e (patch) | |
tree | 5cabdc22f81daacb1ce82a3975580dc3f4261a3c | |
parent | 63ab4ba07b492448844940c347787ba30735b7f2 (diff) | |
download | cpython-6d22cc8e90ccb1e1965b1a4bc79456e2cc1e5a3e.zip cpython-6d22cc8e90ccb1e1965b1a4bc79456e2cc1e5a3e.tar.gz cpython-6d22cc8e90ccb1e1965b1a4bc79456e2cc1e5a3e.tar.bz2 |
bpo-37261: Fix support.catch_unraisable_exception() (GH-14052)
The __exit__() method of test.support.catch_unraisable_exception
context manager now ignores unraisable exception raised when clearing
self.unraisable attribute.
-rw-r--r-- | Doc/library/test.rst | 12 | ||||
-rw-r--r-- | Lib/test/support/__init__.py | 22 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Tests/2019-06-13-12-19-56.bpo-37261.NuKFVo.rst | 3 |
3 files changed, 35 insertions, 2 deletions
diff --git a/Doc/library/test.rst b/Doc/library/test.rst index b7a2595..0a98c88 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -1086,6 +1086,18 @@ 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. + Usage:: with support.catch_unraisable_exception() as cm: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index d6ed221..174e045 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -3040,6 +3040,18 @@ 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. + Usage: with support.catch_unraisable_exception() as cm: @@ -3058,6 +3070,8 @@ class catch_unraisable_exception: 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): @@ -3066,6 +3080,10 @@ class catch_unraisable_exception: 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 diff --git a/Misc/NEWS.d/next/Tests/2019-06-13-12-19-56.bpo-37261.NuKFVo.rst b/Misc/NEWS.d/next/Tests/2019-06-13-12-19-56.bpo-37261.NuKFVo.rst new file mode 100644 index 0000000..27ce78a --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-06-13-12-19-56.bpo-37261.NuKFVo.rst @@ -0,0 +1,3 @@ +Fix :func:`test.support.catch_unraisable_exception`: its __exit__() method +now ignores unraisable exception raised when clearing its ``unraisable`` +attribute. |