Skip to content

Commit 39a2bcf

Browse files
authored
gh-143547: Fix PyErr_FormatUnraisable() fallback (#143557)
Hold a strong reference to 'hook' while calling the default unraisable took to log hook failure. Fix test_sys.UnraisableHookTest: use the right decorator function to disable colors. Previously, tests were always skipped.
1 parent 6d54b6a commit 39a2bcf

File tree

3 files changed

+7
-5
lines changed

3 files changed

+7
-5
lines changed

Lib/test/test_sys.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1350,7 +1350,7 @@ def test_disable_gil_abi(self):
13501350

13511351

13521352
@test.support.cpython_only
1353-
@force_not_colorized
1353+
@test.support.force_not_colorized_test_class
13541354
class UnraisableHookTest(unittest.TestCase):
13551355
def test_original_unraisablehook(self):
13561356
_testcapi = import_helper.import_module('_testcapi')
@@ -1492,6 +1492,7 @@ def hook_func(args):
14921492
def test_custom_unraisablehook_fail(self):
14931493
_testcapi = import_helper.import_module('_testcapi')
14941494
from _testcapi import err_writeunraisable
1495+
14951496
def hook_func(*args):
14961497
raise Exception("hook_func failed")
14971498

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :func:`sys.unraisablehook` when the hook raises an exception and changes
2+
:func:`sys.unraisablehook`: hold a strong reference to the old hook. Patch
3+
by Victor Stinner.

Python/errors.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,7 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
16561656
_Py_EnsureTstateNotNULL(tstate);
16571657

16581658
PyObject *err_msg = NULL;
1659+
PyObject *hook = NULL;
16591660
PyObject *exc_type, *exc_value, *exc_tb;
16601661
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
16611662

@@ -1700,7 +1701,6 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
17001701
goto error;
17011702
}
17021703

1703-
PyObject *hook;
17041704
if (PySys_GetOptionalAttr(&_Py_ID(unraisablehook), &hook) < 0) {
17051705
Py_DECREF(hook_args);
17061706
err_msg_str = NULL;
@@ -1713,21 +1713,18 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
17131713
}
17141714

17151715
if (_PySys_Audit(tstate, "sys.unraisablehook", "OO", hook, hook_args) < 0) {
1716-
Py_DECREF(hook);
17171716
Py_DECREF(hook_args);
17181717
err_msg_str = "Exception ignored in audit hook";
17191718
obj = NULL;
17201719
goto error;
17211720
}
17221721

17231722
if (hook == Py_None) {
1724-
Py_DECREF(hook);
17251723
Py_DECREF(hook_args);
17261724
goto default_hook;
17271725
}
17281726

17291727
PyObject *res = PyObject_CallOneArg(hook, hook_args);
1730-
Py_DECREF(hook);
17311728
Py_DECREF(hook_args);
17321729
if (res != NULL) {
17331730
Py_DECREF(res);
@@ -1757,6 +1754,7 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
17571754
Py_XDECREF(exc_value);
17581755
Py_XDECREF(exc_tb);
17591756
Py_XDECREF(err_msg);
1757+
Py_XDECREF(hook);
17601758
_PyErr_Clear(tstate); /* Just in case */
17611759
}
17621760

0 commit comments

Comments
 (0)