Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion Lib/test/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from test.support import (TESTFN, captured_stderr, check_impl_detail,
check_warnings, cpython_only, gc_collect, run_unittest,
no_tracing, unlink, import_module)
no_tracing, unlink, import_module, script_helper)

class NaiveException(Exception):
def __init__(self, x):
Expand Down Expand Up @@ -1097,6 +1097,23 @@ def test_unhandled(self):
self.assertIn("test message", report)
self.assertTrue(report.endswith("\n"))

@cpython_only
def test_memory_error_in_PyErr_PrintEx(self):
code = """if 1:
import _testcapi
class C(): pass
_testcapi.set_nomemory(0, %d)
C()
"""

# Issue #30817: Abort in PyErr_PrintEx() when no memory.
# Span a large range of tests as the CPython code always evolves with
# changes that add or remove memory allocations.
for i in range(1, 20):
rc, out, err = script_helper.assert_python_failure("-c", code % i)
self.assertIn(rc, (1, 120))
self.assertIn(b'MemoryError', err)

def test_yield_in_nested_try_excepts(self):
#Issue #25612
class MainError(Exception):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
`PyErr_PrintEx()` clears now the ignored exception that may be raised by
`_PySys_SetObjectId()`, for example when no memory.
12 changes: 9 additions & 3 deletions Python/pythonrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,15 @@ PyErr_PrintEx(int set_sys_last_vars)
return;
/* Now we know v != NULL too */
if (set_sys_last_vars) {
_PySys_SetObjectId(&PyId_last_type, exception);
_PySys_SetObjectId(&PyId_last_value, v);
_PySys_SetObjectId(&PyId_last_traceback, tb);
if (_PySys_SetObjectId(&PyId_last_type, exception) < 0) {
PyErr_Clear();
}
if (_PySys_SetObjectId(&PyId_last_value, v) < 0) {
PyErr_Clear();
}
if (_PySys_SetObjectId(&PyId_last_traceback, tb) < 0) {
PyErr_Clear();
}
}
hook = _PySys_GetObjectId(&PyId_excepthook);
if (hook) {
Expand Down