From 63dd27da3ba17a9584907cf179c0f33ba92de98a Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Fri, 19 Sep 2025 11:09:44 -0400 Subject: [PATCH] [3.13] gh-112729: Correctly fail when the process is out of memory during interpreter creation (GH-139164) (GH-139169) * gh-112729: Correctly fail when the process is out of memory during interpreter creation (GH-139164) (cherry picked from commit d06113c7a7cac76a28847702685e601b79f71bf8) --- Lib/test/test_interpreters/test_stress.py | 9 +++++++++ ...25-09-19-09-36-42.gh-issue-112729.mmty0_.rst | 2 ++ Python/pylifecycle.c | 17 ++++++++--------- 3 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-09-19-09-36-42.gh-issue-112729.mmty0_.rst diff --git a/Lib/test/test_interpreters/test_stress.py b/Lib/test/test_interpreters/test_stress.py index fae2f38cb55..a39c9352f72 100644 --- a/Lib/test/test_interpreters/test_stress.py +++ b/Lib/test/test_interpreters/test_stress.py @@ -7,6 +7,7 @@ from test.support import threading_helper # Raise SkipTest if subinterpreters not supported. import_helper.import_module('_interpreters') from test.support import interpreters +from test.support.interpreters import InterpreterError from .utils import TestBase @@ -74,6 +75,14 @@ class StressTests(TestBase): start.set() support.gc_collect() + def test_create_interpreter_no_memory(self): + import _interpreters + _testcapi = import_helper.import_module("_testcapi") + + with self.assertRaises(InterpreterError): + _testcapi.set_nomemory(0, 1) + _interpreters.create() + if __name__ == '__main__': # Test needs to be a package, so we can do relative imports. diff --git a/Misc/NEWS.d/next/Library/2025-09-19-09-36-42.gh-issue-112729.mmty0_.rst b/Misc/NEWS.d/next/Library/2025-09-19-09-36-42.gh-issue-112729.mmty0_.rst new file mode 100644 index 00000000000..07485fcf9f1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-19-09-36-42.gh-issue-112729.mmty0_.rst @@ -0,0 +1,2 @@ +Fix crash when calling ``_interpreters.create`` when the +process is out of memory. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 01fd36e52fc..8cc6bd0fa78 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2301,17 +2301,16 @@ new_interpreter(PyThreadState **tstate_p, interpreters: disable PyGILState_Check(). */ runtime->gilstate.check_enabled = 0; - PyInterpreterState *interp = PyInterpreterState_New(); - if (interp == NULL) { - *tstate_p = NULL; - return _PyStatus_OK(); - } - _PyInterpreterState_SetWhence(interp, whence); - interp->_ready = 1; - // XXX Might new_interpreter() have been called without the GIL held? PyThreadState *save_tstate = _PyThreadState_GET(); PyThreadState *tstate = NULL; + PyInterpreterState *interp; + status = _PyInterpreterState_New(save_tstate, &interp); + if (interp == NULL) { + goto error; + } + _PyInterpreterState_SetWhence(interp, whence); + interp->_ready = 1; /* From this point until the init_interp_create_gil() call, we must not do anything that requires that the GIL be held @@ -2388,7 +2387,7 @@ error: *tstate_p = NULL; if (tstate != NULL) { Py_EndInterpreter(tstate); - } else { + } else if (interp != NULL) { PyInterpreterState_Delete(interp); } if (save_tstate != NULL) {