https://github.com/python/cpython/commit/1ec36a62ebcba5c47c92717f6f021c081f095063
commit: 1ec36a62ebcba5c47c92717f6f021c081f095063
branch: 3.13
author: Peter Bierma <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-01-14T13:33:52+05:30
summary:

[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 <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-01-11-12-39-17.gh-issue-128717.i65d06.rst
M Lib/test/test_sys.py
M Python/ceval.c

diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 400577d36cd44d..01ce0118651b75 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -362,6 +362,36 @@ def test_setrecursionlimit_to_depth(self):
         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 00000000000000..212c6d3cb97216
--- /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 <free threading>` build.
diff --git a/Python/ceval.c b/Python/ceval.c
index 04dd0840519c37..2f67d40874ba41 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()

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to