blob: 398abebc16f9e896e5a4b872b77c3c8b3ae23d69 [file] [log] [blame]
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +00001#! /usr/bin/env python
2"""Find the maximum recursion limit that prevents core dumps
3
4This script finds the maximum safe recursion limit on a particular
5platform. If you need to change the recursion limit on your system,
6this script will tell you a safe upper bound. To use the new limit,
7call sys.setrecursionlimit.
8
9This module implements several ways to create infinite recursion in
10Python. Different implementations end up pushing different numbers of
11C stack frames, depending on how many calls through Python's abstract
12C API occur.
13
14After each round of tests, it prints a message
15Limit of NNNN is fine.
16
17It ends when Python causes a segmentation fault because the limit is
18too high. On platforms like Mac and Windows, it should exit with a
19MemoryError.
20
21NB: A program that does not use __methods__ can set a higher limit.
22"""
23
24import sys
Amaury Forgeot d'Arc24cb3822008-09-11 20:56:13 +000025import itertools
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000026
27class RecursiveBlowup1:
28 def __init__(self):
29 self.__init__()
30
31def test_init():
32 return RecursiveBlowup1()
33
34class RecursiveBlowup2:
35 def __repr__(self):
36 return repr(self)
37
38def test_repr():
39 return repr(RecursiveBlowup2())
40
41class RecursiveBlowup4:
42 def __add__(self, x):
43 return x + self
44
45def test_add():
46 return RecursiveBlowup4() + RecursiveBlowup4()
47
48class RecursiveBlowup5:
49 def __getattr__(self, attr):
50 return getattr(self, attr)
51
52def test_getattr():
53 return RecursiveBlowup5().attr
54
55class RecursiveBlowup6:
56 def __getitem__(self, item):
57 return self[item - 2] + self[item - 1]
58
59def test_getitem():
60 return RecursiveBlowup6()[5]
Tim Peters182b5ac2004-07-18 06:16:08 +000061
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000062def test_recurse():
63 return test_recurse()
64
Amaury Forgeot d'Arc24cb3822008-09-11 20:56:13 +000065def test_cpickle(_cache={}):
66 try:
67 import cPickle
68 except ImportError:
69 print "cannot import cPickle, skipped!"
70 return
71 l = None
72 for n in itertools.count():
73 try:
74 l = _cache[n]
75 continue # Already tried and it works, let's save some time
76 except KeyError:
77 for i in range(100):
78 l = [l]
79 cPickle.dumps(l, protocol=-1)
80 _cache[n] = l
81
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000082def check_limit(n, test_func_name):
83 sys.setrecursionlimit(n)
84 if test_func_name.startswith("test_"):
85 print test_func_name[5:]
86 else:
87 print test_func_name
88 test_func = globals()[test_func_name]
89 try:
90 test_func()
91 except RuntimeError:
92 pass
93 else:
94 print "Yikes!"
95
96limit = 1000
97while 1:
98 check_limit(limit, "test_recurse")
99 check_limit(limit, "test_add")
100 check_limit(limit, "test_repr")
101 check_limit(limit, "test_init")
102 check_limit(limit, "test_getattr")
103 check_limit(limit, "test_getitem")
Amaury Forgeot d'Arc24cb3822008-09-11 20:56:13 +0000104 check_limit(limit, "test_cpickle")
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +0000105 print "Limit of %d is fine" % limit
106 limit = limit + 100