[Python-checkins] r70344 - in python/branches/py3k: Include/ceval.h Lib/test/test_sys.py Misc/NEWS
antoine.pitrou
python-checkins at python.org
Fri Mar 13 20:25:21 CET 2009
Author: antoine.pitrou
Date: Fri Mar 13 20:25:20 2009
New Revision: 70344
Log:
Issue #5392: when a very low recursion limit was set, the interpreter would
abort with a fatal error after the recursion limit was hit twice.
Modified:
python/branches/py3k/Include/ceval.h
python/branches/py3k/Lib/test/test_sys.py
python/branches/py3k/Misc/NEWS
Modified: python/branches/py3k/Include/ceval.h
==============================================================================
--- python/branches/py3k/Include/ceval.h (original)
+++ python/branches/py3k/Include/ceval.h Fri Mar 13 20:25:20 2009
@@ -92,11 +92,10 @@
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
#endif
-#ifdef USE_STACKCHECK
-# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50)
-#else
-# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50)
-#endif
+#define _Py_MakeEndRecCheck(x) \
+ (--(x) < ((_Py_CheckRecursionLimit > 100) \
+ ? (_Py_CheckRecursionLimit - 50) \
+ : (3 * (_Py_CheckRecursionLimit >> 2))))
#define Py_ALLOW_RECURSION \
do { unsigned char _old = PyThreadState_GET()->recursion_critical;\
Modified: python/branches/py3k/Lib/test/test_sys.py
==============================================================================
--- python/branches/py3k/Lib/test/test_sys.py (original)
+++ python/branches/py3k/Lib/test/test_sys.py Fri Mar 13 20:25:20 2009
@@ -2,6 +2,8 @@
import unittest, test.support
import sys, io, os
import struct
+import subprocess
+import textwrap
class SysModuleTest(unittest.TestCase):
@@ -155,6 +157,46 @@
self.assertEqual(sys.getrecursionlimit(), 10000)
sys.setrecursionlimit(oldlimit)
+ def test_recursionlimit_recovery(self):
+ # 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)
+ self.assertRaises(RuntimeError, f)
+ self.assertRaises(RuntimeError, f)
+ 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.
+ code = textwrap.dedent("""
+ import sys
+
+ def f():
+ try:
+ f()
+ except RuntimeError:
+ f()
+
+ sys.setrecursionlimit(%d)
+ f()""")
+ for i in (50, 1000):
+ sub = subprocess.Popen([sys.executable, '-c', code % i],
+ stderr=subprocess.PIPE)
+ err = sub.communicate()[1]
+ self.assertTrue(sub.returncode, sub.returncode)
+ self.assertTrue(
+ b"Fatal Python error: Cannot recover from stack overflow" in err,
+ err)
+
def test_getwindowsversion(self):
if hasattr(sys, "getwindowsversion"):
v = sys.getwindowsversion()
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Fri Mar 13 20:25:20 2009
@@ -12,6 +12,9 @@
Core and Builtins
-----------------
+- Issue #5392: when a very low recursion limit was set, the interpreter would
+ abort with a fatal error after the recursion limit was hit twice.
+
Library
-------
@@ -24,8 +27,6 @@
Core and Builtins
-----------------
-=======
-
- The io module has been reimplemented in C for speed.
- Give dict views an informative __repr__.
More information about the Python-checkins
mailing list