From 8c50ad21567db10a9747f1b5fa39827b4ce3e025 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 29 Sep 2023 22:00:56 +0200 Subject: [PATCH 1/2] gh-108851: Fix support.get_recursion_available() for USE_STACKCHECK USE_STACKCHECK on using on Windows 32-bit. --- Lib/test/support/__init__.py | 3 ++- Lib/test/test_support.py | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 2c6b22fdee5a21..c21211b9b8ef30 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2243,7 +2243,8 @@ def get_recursion_available(): """ limit = sys.getrecursionlimit() depth = get_recursion_depth() - return limit - depth + # -1 for USE_STACKCHECK + return max(limit - depth - 1, 0) @contextlib.contextmanager def set_recursion_limit(limit): diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 9894c2647d7c93..7285605d66d7bc 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -732,15 +732,17 @@ def test_recursive(depth, limit): 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) + # Use limit-3 since f-string seems to consume 2 frames + # and -1 for USE_STACKCHECK. + test_recursive(2, limit - 3) # 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) + # Use limit-3 since f-string seems to consume 2 frames + # and -1 for USE_STACKCHECK. + test_recursive(2, limit - 3) """) script_helper.assert_python_ok("-c", code) From 009a98dde0bda21fcc0f0a591a77056bc1ca3dcb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 29 Sep 2023 23:10:38 +0200 Subject: [PATCH 2/2] Add _testcapi.USE_STACKCHECK --- Lib/test/support/__init__.py | 12 ++++++++++-- Lib/test/test_support.py | 19 +++++++++++++------ Modules/_testcapimodule.c | 10 ++++++++-- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index c21211b9b8ef30..2e6518cf241f14 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2243,8 +2243,16 @@ def get_recursion_available(): """ limit = sys.getrecursionlimit() depth = get_recursion_depth() - # -1 for USE_STACKCHECK - return max(limit - depth - 1, 0) + + 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 7285605d66d7bc..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,21 +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-3 since f-string seems to consume 2 frames - # and -1 for USE_STACKCHECK. - test_recursive(2, limit - 3) + 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}") - # Use limit-3 since f-string seems to consume 2 frames - # and -1 for USE_STACKCHECK. - test_recursive(2, limit - 3) + 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);