From: Peter Bierma Date: Tue, 14 Jan 2025 08:03:52 +0000 (-0500) Subject: [3.13] gh-128717: Stop-the-world when setting the recursion limit (GH-128741) (#128757) X-Git-Tag: v3.13.2~105 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1ec36a62ebcba5c47c92717f6f021c081f095063;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-128717: Stop-the-world when setting the recursion limit (GH-128741) (#128757) [3.13] gh-128717: Stop-the-world when setting the recursion limit (GH-128741) (cherry picked from commit f6c61bf2d7d8b66ccd9f16e723546bdcc251a3d0) Co-authored-by: Peter Bierma --- diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 400577d36cd4..01ce0118651b 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -362,6 +362,36 @@ class SysModuleTest(unittest.TestCase): finally: sys.setrecursionlimit(old_limit) + @unittest.skipUnless(support.Py_GIL_DISABLED, "only meaningful if the GIL is disabled") + @threading_helper.requires_working_threading() + def test_racing_recursion_limit(self): + from threading import Thread + def something_recursive(): + def count(n): + if n > 0: + return count(n - 1) + 1 + return 0 + + count(50) + + def set_recursion_limit(): + for limit in range(100, 200): + sys.setrecursionlimit(limit) + + threads = [] + for _ in range(5): + threads.append(Thread(target=set_recursion_limit)) + + for _ in range(5): + threads.append(Thread(target=something_recursive)) + + with threading_helper.catch_threading_exception() as cm: + with threading_helper.start_threads(threads): + pass + + if cm.exc_value: + raise cm.exc_value + def test_getwindowsversion(self): # Raise SkipTest if sys doesn't have getwindowsversion attribute test.support.get_attribute(sys, "getwindowsversion") diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-11-12-39-17.gh-issue-128717.i65d06.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-11-12-39-17.gh-issue-128717.i65d06.rst new file mode 100644 index 000000000000..212c6d3cb972 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-11-12-39-17.gh-issue-128717.i65d06.rst @@ -0,0 +1,2 @@ +Fix a crash when setting the recursion limit while other threads are active +on the :term:`free threaded ` build. diff --git a/Python/ceval.c b/Python/ceval.c index 04dd0840519c..2f67d40874ba 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -265,12 +265,16 @@ void Py_SetRecursionLimit(int new_limit) { PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyEval_StopTheWorld(interp); + HEAD_LOCK(interp->runtime); interp->ceval.recursion_limit = new_limit; for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) { int depth = p->py_recursion_limit - p->py_recursion_remaining; p->py_recursion_limit = new_limit; p->py_recursion_remaining = new_limit - depth; } + HEAD_UNLOCK(interp->runtime); + _PyEval_StartTheWorld(interp); } /* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()