2
"""Find the maximum recursion limit that prevents interpreter termination.
4
This script finds the maximum safe recursion limit on a particular
5
platform. If you need to change the recursion limit on your system,
6
this script will tell you a safe upper bound. To use the new limit,
7
call sys.setrecursionlimit().
9
This module implements several ways to create infinite recursion in
10
Python. Different implementations end up pushing different numbers of
11
C stack frames, depending on how many calls through Python's abstract
14
After each round of tests, it prints a message:
15
"Limit of NNNN is fine".
17
The highest printed value of "NNNN" is therefore the highest potentially
18
safe limit for your system (which depends on the OS, architecture, but also
19
the compilation flags). Please note that it is practically impossible to
20
test all possible recursion paths in the interpreter, so the results of
21
this test should not be trusted blindly -- although they give a good hint
22
of which values are reasonable.
24
NOTE: When the C stack space allocated by your system is exceeded due
25
to excessive recursion, exact behaviour depends on the platform, although
26
the interpreter will always fail in a likely brutal way: either a
27
segmentation fault, a MemoryError, or just a silent abort.
29
NB: A program that does not use __methods__ can set a higher limit.
35
class RecursiveBlowup1:
40
return RecursiveBlowup1()
42
class RecursiveBlowup2:
47
return repr(RecursiveBlowup2())
49
class RecursiveBlowup4:
54
return RecursiveBlowup4() + RecursiveBlowup4()
56
class RecursiveBlowup5:
57
def __getattr__(self, attr):
58
return getattr(self, attr)
61
return RecursiveBlowup5().attr
63
class RecursiveBlowup6:
64
def __getitem__(self, item):
65
return self[item - 2] + self[item - 1]
68
return RecursiveBlowup6()[5]
73
def test_cpickle(_cache={}):
78
print("cannot import _pickle, skipped!")
81
for n in itertools.count():
84
continue # Already tried and it works, let's save some time
88
_pickle.Pickler(io.BytesIO(), protocol=-1).dump(l)
91
def check_limit(n, test_func_name):
92
sys.setrecursionlimit(n)
93
if test_func_name.startswith("test_"):
94
print(test_func_name[5:])
97
test_func = globals()[test_func_name]
100
# AttributeError can be raised because of the way e.g. PyDict_GetItem()
101
# silences all exceptions and returns NULL, which is usually interpreted
102
# as "missing attribute".
103
except (RuntimeError, AttributeError):
110
check_limit(limit, "test_recurse")
111
check_limit(limit, "test_add")
112
check_limit(limit, "test_repr")
113
check_limit(limit, "test_init")
114
check_limit(limit, "test_getattr")
115
check_limit(limit, "test_getitem")
116
check_limit(limit, "test_cpickle")
117
print("Limit of %d is fine" % limit)