@@ -219,7 +219,7 @@ def test_recursionlimit_recovery(self):
219219 def f ():
220220 f ()
221221 try :
222- for depth in (50 , 75 , 100 , 250 , 1000 ):
222+ for depth in (10 , 25 , 50 , 75 , 100 , 250 , 1000 ):
223223 try :
224224 sys .setrecursionlimit (depth )
225225 except RecursionError :
@@ -229,17 +229,17 @@ def f():
229229
230230 # Issue #5392: test stack overflow after hitting recursion
231231 # limit twice
232- with self .assertRaises (RecursionError ):
233- f ()
234- with self .assertRaises (RecursionError ):
235- f ()
232+ self .assertRaises (RecursionError , f )
233+ self .assertRaises (RecursionError , f )
236234 finally :
237235 sys .setrecursionlimit (oldlimit )
238236
239237 @test .support .cpython_only
240238 def test_setrecursionlimit_recursion_depth (self ):
241239 # Issue #25274: Setting a low recursion limit must be blocked if the
242- # current recursion depth is already higher than limit.
240+ # current recursion depth is already higher than the "lower-water
241+ # mark". Otherwise, it may not be possible anymore to
242+ # reset the overflowed flag to 0.
243243
244244 from _testinternalcapi import get_recursion_depth
245245
@@ -260,10 +260,42 @@ def set_recursion_limit_at_depth(depth, limit):
260260 sys .setrecursionlimit (1000 )
261261
262262 for limit in (10 , 25 , 50 , 75 , 100 , 150 , 200 ):
263- set_recursion_limit_at_depth (limit , limit )
263+ # formula extracted from _Py_RecursionLimitLowerWaterMark()
264+ if limit > 200 :
265+ depth = limit - 50
266+ else :
267+ depth = limit * 3 // 4
268+ set_recursion_limit_at_depth (depth , limit )
264269 finally :
265270 sys .setrecursionlimit (oldlimit )
266271
272+ # The error message is specific to CPython
273+ @test .support .cpython_only
274+ def test_recursionlimit_fatalerror (self ):
275+ # A fatal error occurs if a second recursion limit is hit when recovering
276+ # from a first one.
277+ code = textwrap .dedent ("""
278+ import sys
279+
280+ def f():
281+ try:
282+ f()
283+ except RecursionError:
284+ f()
285+
286+ sys.setrecursionlimit(%d)
287+ f()""" )
288+ with test .support .SuppressCrashReport ():
289+ for i in (50 , 1000 ):
290+ sub = subprocess .Popen ([sys .executable , '-c' , code % i ],
291+ stderr = subprocess .PIPE )
292+ err = sub .communicate ()[1 ]
293+ self .assertTrue (sub .returncode , sub .returncode )
294+ self .assertIn (
295+ b"Fatal Python error: _Py_CheckRecursiveCall: "
296+ b"Cannot recover from stack overflow" ,
297+ err )
298+
267299 def test_getwindowsversion (self ):
268300 # Raise SkipTest if sys doesn't have getwindowsversion attribute
269301 test .support .get_attribute (sys , "getwindowsversion" )
0 commit comments