8000 [3.13] gh-128717: Stop-the-world when setting the recursion limit (GH… · python/cpython@1ec36a6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1ec36a6

Browse files
[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 f6c61bf) Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
1 parent f2a2809 commit 1ec36a6

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

Lib/test/test_sys.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,36 @@ def test_setrecursionlimit_to_depth(self):
362362
finally:
363363
sys.setrecursionlimit(old_limit)
364364

365+
@unittest.skipUnless(support.Py_GIL_DISABLED, "only meaningful if the GIL is disabled")
366+
@threading_helper.requires_working_threading()
367+
def test_racing_recursion_limit(self):
368+
from threading import Thread
369+
def something_recursive():
370+
def count(n):
371+
if n > 0:
372+
return count(n - 1) + 1
373+
return 0
374+
375+
count(50)
376+
377+
def set_recursion_limit():
378+
for limit in range(100, 200):
379+
sys.setrecursionlimit(limit)
380+
381+
threads = []
382+
for _ in range(5):
383+
threads.append(Thread(target=set_recursion_limit))
384+
385+
for _ in range(5):
386+
threads.append(Thread(target=something_recursive))
387+
388+
with threading_helper.catch_threading_exception() as cm:
389+
with threading_helper.start_threads(threads):
390+
pass
391+
392+
if cm.exc_value:
393+
raise cm.exc_value
394+
365395
def test_getwindowsversion(self):
366396
# Raise SkipTest if sys doesn't have getwindowsversion attribute
367397
test.support.get_attribute(sys, "getwindowsversion")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash when setting the recursion limit while other threads are active
2+
on the :term:`free threaded <free threading>` build.

Python/ceval.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,16 @@ void
265265
Py_SetRecursionLimit(int new_limit)
266266
{
267267
PyInterpreterState *interp = _PyInterpreterState_GET();
268+
_PyEval_StopTheWorld(interp);
269+
HEAD_LOCK(interp->runtime);
268270
interp->ceval.recursion_limit = new_limit;
269271
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
270272
int depth = p->py_recursion_limit - p->py_recursion_remaining;
271273
p->py_recursion_limit = new_limit;
272274
p->py_recursion_remaining = new_limit - depth;
273275
}
276+
HEAD_UNLOCK(interp->runtime);
277+
_PyEval_StartTheWorld(interp);
274278
}
275279

276280
/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()

0 commit comments

Comments
 (0)
0