← 返回首页
gh-102056: Fix a few bugs in error handling of exception printing code by iritkatriel · Pull Request #102078 · python/cpython · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .c  (1) .py  (1) .rst  (1) All 3 file types selected Viewed files
Conversations
Failed to load comments. Retry
Loading
Jump to
Jump to file
Failed to load files. Retry
Loading
Diff view
Unified
Split
Hide whitespace
Apply and reload
Show whitespace
Diff view
Unified
Split
Hide whitespace
Apply and reload
31 changes: 31 additions & 0 deletions Lib/test/test_threading.py
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1523,6 +1523,37 @@ def run():
self.assertEqual(out, b'')
self.assertNotIn("Unhandled exception", err.decode())

def test_print_exception_gh_102056(self):
# This used to crash. See gh-102056.
script = r"""if True:
import time
import threading
import _thread

def f():
try:
f()
except RecursionError:
f()

def g():
try:
raise ValueError()
except* ValueError:
f()

def h():
time.sleep(1)
_thread.interrupt_main()

t = threading.Thread(target=h)
t.start()
g()
t.join()
"""

assert_python_failure("-c", script)

def test_bare_raise_in_brand_new_thread(self):
def bare_raise():
raise
Expand Down
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix error handling bugs in interpreter's exception printing code, which could cause a crash on infinite recursion.
23 changes: 16 additions & 7 deletions Python/pythonrun.c
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1246,8 +1246,7 @@ print_chained(struct exception_print_context* ctx, PyObject *value,
const char * message, const char *tag)
{
PyObject *f = ctx->file;

if (_Py_EnterRecursiveCall(" in print_chained") < 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

#101966 also tries to fix this! Don't let that stop you from fixing it here though :)

if (_Py_EnterRecursiveCall(" in print_chained")) {
return -1;
}
bool need_close = ctx->need_close;
Expand Down Expand Up @@ -1374,7 +1373,9 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
if (ctx->exception_group_depth == 0) {
ctx->exception_group_depth += 1;
}
print_exception(ctx, value);
if (print_exception(ctx, value) < 0) {
return -1;
}

PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs;
assert(excs && PyTuple_Check(excs));
Expand Down Expand Up @@ -1424,7 +1425,7 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
PyObject *exc = PyTuple_GET_ITEM(excs, i);

if (!truncated) {
if (_Py_EnterRecursiveCall(" in print_exception_group") != 0) {
if (_Py_EnterRecursiveCall(" in print_exception_group")) {
return -1;
}
int res = print_exception_recursive(ctx, exc);
Expand Down Expand Up @@ -1477,22 +1478,30 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
static int
print_exception_recursive(struct exception_print_context *ctx, PyObject *value)
{
if (_Py_EnterRecursiveCall(" in print_exception_recursive")) {
return -1;
}
if (ctx->seen != NULL) {
/* Exception chaining */
if (print_exception_cause_and_context(ctx, value) < 0) {
return -1;
goto error;
}
}
if (!_PyBaseExceptionGroup_Check(value)) {
if (print_exception(ctx, value) < 0) {
return -1;
goto error;
}
}
else if (print_exception_group(ctx, value) < 0) {
return -1;
goto error;
}
assert(!PyErr_Occurred());

_Py_LeaveRecursiveCall();
return 0;
error:
_Py_LeaveRecursiveCall();
return -1;
}

#define PyErr_MAX_GROUP_WIDTH 15
Expand Down
Toggle all file notes Toggle all file annotations

Footer

© 2026 GitHub, Inc.