[3.11] gh-108851: Fix support.get_recursion_available() for USE_STACKCHECK (#110127)

Add _testcapi.USE_STACKCHECK.

USE_STACKCHECK on using on Windows 32-bit.
This commit is contained in:
Victor Stinner 2023-09-29 23:54:46 +02:00 committed by GitHub
parent a95e8cf908
commit 190e8fbfb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 7 deletions

View File

@ -2243,7 +2243,16 @@ def get_recursion_available():
"""
limit = sys.getrecursionlimit()
depth = get_recursion_depth()
return limit - depth
try:
from _testcapi import USE_STACKCHECK
except ImportError:
USE_STACKCHECK = False
if USE_STACKCHECK:
return max(limit - depth - 1, 0)
else:
return limit - depth
@contextlib.contextmanager
def set_recursion_limit(limit):

View File

@ -704,6 +704,10 @@ def test_get_recursion_depth(self):
code = textwrap.dedent("""
from test import support
import sys
try:
from _testcapi import USE_STACKCHECK
except ImportError:
USE_STACKCHECK = False
def check(cond):
if not cond:
@ -728,19 +732,24 @@ def test_recursive(depth, limit):
check(get_depth == depth)
test_recursive(depth + 1, limit)
if USE_STACKCHECK:
# f-string consumes 2 frames and -1 for USE_STACKCHECK
IGNORE = 3
else:
# f-string consumes 2 frames
IGNORE = 2
# depth up to 25
with support.infinite_recursion(max_depth=25):
limit = sys.getrecursionlimit()
print(f"test with sys.getrecursionlimit()={limit}")
# Use limit-2 since f-string seems to consume 2 frames.
test_recursive(2, limit - 2)
test_recursive(2, limit - IGNORE)
# depth up to 500
with support.infinite_recursion(max_depth=500):
limit = sys.getrecursionlimit()
print(f"test with sys.getrecursionlimit()={limit}")
# limit-2 since f-string seems to consume 2 frames
test_recursive(2, limit - 2)
test_recursive(2, limit - IGNORE)
""")
script_helper.assert_python_ok("-c", code)

View File

@ -8203,8 +8203,14 @@ PyInit__testcapi(void)
#else
v = Py_False;
#endif
Py_INCREF(v);
PyModule_AddObject(m, "WITH_PYMALLOC", v);
PyModule_AddObject(m, "WITH_PYMALLOC", Py_NewRef(v));
#ifdef USE_STACKCHECK
v = Py_True;
#else
v = Py_False;
#endif
PyModule_AddObject(m, "USE_STACKCHECK", Py_NewRef(v));
TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
Py_INCREF(TestError);