From 190e8fbfb7284e9c253388f0c2363cd8387e6e7f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 29 Sep 2023 23:54:46 +0200 Subject: [PATCH] [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. --- Lib/test/support/__init__.py | 11 ++++++++++- Lib/test/test_support.py | 17 +++++++++++++---- Modules/_testcapimodule.c | 10 ++++++++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 2c6b22fdee5a21..2e6518cf241f14 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -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): diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 9894c2647d7c93..2efdbd22d90e2e 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -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) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5c00b48001a919..2f1801f781017d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -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);