Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1202ec6
fix: exec('_testcapi.set_nomemory(0)') hang in new repl 3.13
yihong0618 Sep 4, 2025
4cd38e8
chore: add news for it
yihong0618 Sep 4, 2025
e557017
Update Python/ceval.c
yihong0618 Sep 4, 2025
53f713c
fix: add unittest for it
yihong0618 Sep 4, 2025
9cc89f1
fix: make test info better
yihong0618 Sep 4, 2025
a9b6f96
fix: better test without print
yihong0618 Sep 5, 2025
66ec42e
Update Misc/NEWS.d/next/Core_and_Builtins/2025-09-04-11-52-23.gh-issu…
yihong0618 Sep 5, 2025
a9e6b64
Update Lib/test/test_repl.py
yihong0618 Sep 5, 2025
791ca86
fix: address comments
yihong0618 Sep 5, 2025
4827680
Update Lib/test/test_repl.py
yihong0618 Sep 5, 2025
8ec5769
fix: follow up another comments
yihong0618 Sep 5, 2025
edcfff7
fix: should set the error when no memory
yihong0618 Sep 7, 2025
81c6244
fix: exec('_testcapi.set_nomemory(0)') hang in new repl 3.13
yihong0618 Sep 4, 2025
847bd7b
chore: add news for it
yihong0618 Sep 4, 2025
ff3c7f4
Update Python/ceval.c
yihong0618 Sep 4, 2025
175a13e
fix: add unittest for it
yihong0618 Sep 4, 2025
d952d53
fix: make test info better
yihong0618 Sep 4, 2025
5fa3a1b
fix: better test without print
yihong0618 Sep 5, 2025
d3274fb
Update Misc/NEWS.d/next/Core_and_Builtins/2025-09-04-11-52-23.gh-issu…
yihong0618 Sep 5, 2025
c89c5b5
Update Lib/test/test_repl.py
yihong0618 Sep 5, 2025
63a6b7d
fix: address comments
yihong0618 Sep 5, 2025
977703f
Update Lib/test/test_repl.py
yihong0618 Sep 5, 2025
095f865
fix: follow up another comments
yihong0618 Sep 5, 2025
932c15e
fix: should set the error when no memory
yihong0618 Sep 7, 2025
52310f0
Merge branch '3.13' into hy/fix_issue_134163
ZeroIntensity Sep 7, 2025
bb790af
fix: in TraceRefs it will return fatal error
yihong0618 Sep 9, 2025
06b779a
fix: use support.Py_TRACE_REFS
yihong0618 Sep 9, 2025
30cd34d
Merge branch 'hy/fix_issue_134163' of https://github.com/yihong0618/c…
yihong0618 Sep 9, 2025
26ce31b
fix: use spawn_python
yihong0618 Sep 10, 2025
5ab08c7
fix: address comments
yihong0618 Sep 10, 2025
789040c
Apply suggestions from code review
yihong0618 Sep 10, 2025
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
39 changes: 39 additions & 0 deletions Lib/test/test_repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,45 @@ def test_no_memory(self):
# Exit code 120: Py_FinalizeEx() failed to flush stdout and stderr.
self.assertIn(p.returncode, (1, 120))

@cpython_only
def test_exec_set_nomemory_hang(self):
# gh-134163 Test case that triggers no memory hang condition
user_input = dedent("""
a1 = list(range(1000, 2000))
a2 = list(range(1000, 2000))
a3 = list(range(1000, 2000))
a4 = list(range(1000, 2000))
a5 = list(range(1000, 2000))
a6 = list(range(1000, 2000))
a7 = list(range(1000, 2000))
a8 = list(range(1000, 2000))
a9 = list(range(1000, 2000))
a10 = list(range(1000, 2000))
a11 = list(range(1000, 2000))
a12 = list(range(1000, 2000))
a13 = list(range(1000, 2000))
a14 = list(range(1000, 2000))
try:
import _testcapi
_testcapi.set_nomemory(0)
b = list(range(1000, 2000))
except Exception as e:
import traceback
traceback.print_exc()
""")
p = spawn_repl()
with SuppressCrashReport():
p.stdin.write(user_input)
Copy link
Member

Choose a reason for hiding this comment

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

This is still just running it in the REPL. For now, let's switch to the simple repro of import _testcapi; _testcapi.set_nomemory(0).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

seems not right if so
...it will not hang for 3.13
the test is the same as

    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
    def test_no_memory(self):
        import_module("_testcapi")
        # Issue #30696: Fix the interactive interpreter looping endlessly when
        # no memory. Check also that the fix does not break the interactive
        # loop when an exception is raised.
        user_input = """
            import sys, _testcapi
            1/0
            print('After the exception.')
            _testcapi.set_nomemory(0)
            sys.exit(0)
        """
        user_input = dedent(user_input)
        p = spawn_repl()
        with SuppressCrashReport():
            p.stdin.write(user_input)
        output = kill_python(p)
        self.assertIn('After the exception.', output)
        # Exit code 120: Py_FinalizeEx() failed to flush stdout and stderr.
        self.assertIn(p.returncode, (1, 120))

if we use test
import _testcapi; _testcapi.set_nomemory(0).
it always pass with or without the patch

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I meant that we don't need spawn_repl here. subprocess.run([sys.executable, '-c', user_input]) should work as a test -- there's no need to involve the REPL.

output = kill_python(p)

self.assertIn(p.returncode, (0, 1, 120))
# The key test is that it doesn't hang - if we get output, the test passed
# Look for either successful execution or memory error indicators
has_traceback = "Traceback" in output
has_memory_error = "MemoryError" in output
# Either we get a traceback (expected) or we complete without hanging
self.assertTrue(len(output) > 0, f"Expected some output, got: {output}") # At minimum, should not hang

@cpython_only
def test_multiline_string_parsing(self):
# bpo-39209: Multiline string tokens need to be handled in the tokenizer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fix in default repl exec('_testcapi.set_nomemory(0)') hang forever.
8 changes: 7 additions & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
PyObject *lasti = PyLong_FromLong(frame_lasti);
if (lasti == NULL) {
goto exception_unwind;
// gh-134163: If we can't allocate memory for lasti during exception handling,
// this likely means we're in a severe memory shortage situation.
// Instead of going back to exception_unwind (which would cause
// infinite recursion), directly exit to let the original exception
// propagate up and hopefully be handled at a higher level.
_PyFrame_SetStackPointer(frame, stack_pointer);
goto exit_unwind;
}
PUSH(lasti);
}
Expand Down
Loading