|
2 | 2 | import unittest, test.support |
3 | 3 | import sys, io, os |
4 | 4 | import struct |
| 5 | +import subprocess |
| 6 | +import textwrap |
5 | 7 |
|
6 | 8 | class SysModuleTest(unittest.TestCase): |
7 | 9 |
|
@@ -155,6 +157,46 @@ def test_recursionlimit(self): |
155 | 157 | self.assertEqual(sys.getrecursionlimit(), 10000) |
156 | 158 | sys.setrecursionlimit(oldlimit) |
157 | 159 |
|
| 160 | + def test_recursionlimit_recovery(self): |
| 161 | + # NOTE: this test is slightly fragile in that it depends on the current |
| 162 | + # recursion count when executing the test being low enough so as to |
| 163 | + # trigger the recursion recovery detection in the _Py_MakeEndRecCheck |
| 164 | + # macro (see ceval.h). |
| 165 | + oldlimit = sys.getrecursionlimit() |
| 166 | + def f(): |
| 167 | + f() |
| 168 | + try: |
| 169 | + for i in (50, 1000): |
| 170 | + # Issue #5392: stack overflow after hitting recursion limit twice |
| 171 | + sys.setrecursionlimit(i) |
| 172 | + self.assertRaises(RuntimeError, f) |
| 173 | + self.assertRaises(RuntimeError, f) |
| 174 | + finally: |
| 175 | + sys.setrecursionlimit(oldlimit) |
| 176 | + |
| 177 | + def test_recursionlimit_fatalerror(self): |
| 178 | + # A fatal error occurs if a second recursion limit is hit when recovering |
| 179 | + # from a first one. |
| 180 | + code = textwrap.dedent(""" |
| 181 | + import sys |
| 182 | +
|
| 183 | + def f(): |
| 184 | + try: |
| 185 | + f() |
| 186 | + except RuntimeError: |
| 187 | + f() |
| 188 | +
|
| 189 | + sys.setrecursionlimit(%d) |
| 190 | + f()""") |
| 191 | + for i in (50, 1000): |
| 192 | + sub = subprocess.Popen([sys.executable, '-c', code % i], |
| 193 | + stderr=subprocess.PIPE) |
| 194 | + err = sub.communicate()[1] |
| 195 | + self.assertTrue(sub.returncode, sub.returncode) |
| 196 | + self.assertTrue( |
| 197 | + b"Fatal Python error: Cannot recover from stack overflow" in err, |
| 198 | + err) |
| 199 | + |
158 | 200 | def test_getwindowsversion(self): |
159 | 201 | if hasattr(sys, "getwindowsversion"): |
160 | 202 | v = sys.getwindowsversion() |
|
0 commit comments