mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
[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 f6c61bf2d7
)
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
This commit is contained in:
parent
f2a2809683
commit
1ec36a62eb
3 changed files with 36 additions and 0 deletions
|
@ -362,6 +362,36 @@ class SysModuleTest(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
sys.setrecursionlimit(old_limit)
|
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):
|
def test_getwindowsversion(self):
|
||||||
# Raise SkipTest if sys doesn't have getwindowsversion attribute
|
# Raise SkipTest if sys doesn't have getwindowsversion attribute
|
||||||
test.support.get_attribute(sys, "getwindowsversion")
|
test.support.get_attribute(sys, "getwindowsversion")
|
||||||
|
|
|
@ -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.
|
|
@ -265,12 +265,16 @@ void
|
||||||
Py_SetRecursionLimit(int new_limit)
|
Py_SetRecursionLimit(int new_limit)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
_PyEval_StopTheWorld(interp);
|
||||||
|
HEAD_LOCK(interp->runtime);
|
||||||
interp->ceval.recursion_limit = new_limit;
|
interp->ceval.recursion_limit = new_limit;
|
||||||
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
|
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
|
||||||
int depth = p->py_recursion_limit - p->py_recursion_remaining;
|
int depth = p->py_recursion_limit - p->py_recursion_remaining;
|
||||||
p->py_recursion_limit = new_limit;
|
p->py_recursion_limit = new_limit;
|
||||||
p->py_recursion_remaining = new_limit - depth;
|
p->py_recursion_remaining = new_limit - depth;
|
||||||
}
|
}
|
||||||
|
HEAD_UNLOCK(interp->runtime);
|
||||||
|
_PyEval_StartTheWorld(interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
|
/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue