summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_sys.py
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-10-12 22:11:21 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2015-10-12 22:11:21 (GMT)
commit50856d5ae745d1c9f691afbd78572bf073c941cf (patch)
treed628ac3d10d0fa02551a8a45d43c03d948306600 /Lib/test/test_sys.py
parent60f26691f5aeff555f27c62aee11efb07e20ecdc (diff)
downloadcpython-50856d5ae745d1c9f691afbd78572bf073c941cf.zip
cpython-50856d5ae745d1c9f691afbd78572bf073c941cf.tar.gz
cpython-50856d5ae745d1c9f691afbd78572bf073c941cf.tar.bz2
sys.setrecursionlimit() now raises RecursionError
Issue #25274: sys.setrecursionlimit() now raises a RecursionError if the new recursion limit is too low depending at the current recursion depth. Modify also the "lower-water mark" formula to make it monotonic. This mark is used to decide when the overflowed flag of the thread state is reset.
Diffstat (limited to 'Lib/test/test_sys.py')
-rw-r--r--Lib/test/test_sys.py52
1 files changed, 45 insertions, 7 deletions
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 8ec38c8..2d95653 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -201,22 +201,60 @@ class SysModuleTest(unittest.TestCase):
if hasattr(sys, 'gettrace') and sys.gettrace():
self.skipTest('fatal error if run with a trace function')
- # NOTE: this test is slightly fragile in that it depends on the current
- # recursion count when executing the test being low enough so as to
- # trigger the recursion recovery detection in the _Py_MakeEndRecCheck
- # macro (see ceval.h).
oldlimit = sys.getrecursionlimit()
def f():
f()
try:
- for i in (50, 1000):
- # Issue #5392: stack overflow after hitting recursion limit twice
- sys.setrecursionlimit(i)
+ for depth in (10, 25, 50, 75, 100, 250, 1000):
+ try:
+ sys.setrecursionlimit(depth)
+ except RecursionError:
+ # Issue #25274: The recursion limit is too low at the
+ # current recursion depth
+ continue
+
+ # Issue #5392: test stack overflow after hitting recursion
+ # limit twice
self.assertRaises(RecursionError, f)
self.assertRaises(RecursionError, f)
finally:
sys.setrecursionlimit(oldlimit)
+ @test.support.cpython_only
+ def test_setrecursionlimit_recursion_depth(self):
+ # Issue #25274: Setting a low recursion limit must be blocked if the
+ # current recursion depth is already higher than the "lower-water
+ # mark". Otherwise, it may not be possible anymore to
+ # reset the overflowed flag to 0.
+
+ from _testcapi import get_recursion_depth
+
+ def set_recursion_limit_at_depth(depth, limit):
+ recursion_depth = get_recursion_depth()
+ if recursion_depth >= depth:
+ with self.assertRaises(RecursionError) as cm:
+ sys.setrecursionlimit(limit)
+ self.assertRegex(str(cm.exception),
+ "cannot set the recursion limit to [0-9]+ "
+ "at the recursion depth [0-9]+: "
+ "the limit is too low")
+ else:
+ set_recursion_limit_at_depth(depth, limit)
+
+ oldlimit = sys.getrecursionlimit()
+ try:
+ sys.setrecursionlimit(1000)
+
+ for limit in (10, 25, 50, 75, 100, 150, 200):
+ # formula extracted from _Py_RecursionLimitLowerWaterMark()
+ if limit > 200:
+ depth = limit - 50
+ else:
+ depth = limit * 3 // 4
+ set_recursion_limit_at_depth(depth, limit)
+ finally:
+ sys.setrecursionlimit(oldlimit)
+
def test_recursionlimit_fatalerror(self):
# A fatal error occurs if a second recursion limit is hit when recovering
# from a first one.