@@ -201,22 +201,60 @@ def test_recursionlimit_recovery(self):
201201 if hasattr (sys , 'gettrace' ) and sys .gettrace ():
202202 self .skipTest ('fatal error if run with a trace function' )
203203
204- # NOTE: this test is slightly fragile in that it depends on the current
205- # recursion count when executing the test being low enough so as to
206- # trigger the recursion recovery detection in the _Py_MakeEndRecCheck
207- # macro (see ceval.h).
208204 oldlimit = sys .getrecursionlimit ()
209205 def f ():
210206 f ()
211207 try :
212- for i in (50 , 1000 ):
213- # Issue #5392: stack overflow after hitting recursion limit twice
214- sys .setrecursionlimit (i )
208+ for depth in (10 , 25 , 50 , 75 , 100 , 250 , 1000 ):
209+ try :
210+ sys .setrecursionlimit (depth )
211+ except RecursionError :
212+ # Issue #25274: The recursion limit is too low at the
213+ # current recursion depth
214+ continue
215+
216+ # Issue #5392: test stack overflow after hitting recursion
217+ # limit twice
215218 self .assertRaises (RecursionError , f )
216219 self .assertRaises (RecursionError , f )
217220 finally :
218221 sys .setrecursionlimit (oldlimit )
219222
223+ @test .support .cpython_only
224+ def test_setrecursionlimit_recursion_depth (self ):
225+ # Issue #25274: Setting a low recursion limit must be blocked if the
226+ # current recursion depth is already higher than the "lower-water
227+ # mark". Otherwise, it may not be possible anymore to
228+ # reset the overflowed flag to 0.
229+
230+ from _testcapi import get_recursion_depth
231+
232+ def set_recursion_limit_at_depth (depth , limit ):
233+ recursion_depth = get_recursion_depth ()
234+ if recursion_depth >= depth :
235+ with self .assertRaises (RecursionError ) as cm :
236+ sys .setrecursionlimit (limit )
237+ self .assertRegex (str (cm .exception ),
238+ "cannot set the recursion limit to [0-9]+ "
239+ "at the recursion depth [0-9]+: "
240+ "the limit is too low" )
241+ else :
242+ set_recursion_limit_at_depth (depth , limit )
243+
244+ oldlimit = sys .getrecursionlimit ()
245+ try :
246+ sys .setrecursionlimit (1000 )
247+
248+ for limit in (10 , 25 , 50 , 75 , 100 , 150 , 200 ):
249+ # formula extracted from _Py_RecursionLimitLowerWaterMark()
250+ if limit > 200 :
251+ depth = limit - 50
252+ else :
253+ depth = limit * 3 // 4
254+ set_recursion_limit_at_depth (depth , limit )
255+ finally :
256+ sys .setrecursionlimit (oldlimit )
257+
220258 def test_recursionlimit_fatalerror (self ):
221259 # A fatal error occurs if a second recursion limit is hit when recovering
222260 # from a first one.
0 commit comments