blob: 295e0940ead997207673d03538d6e21e60a637ee [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.
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000020"""
21
22import sys
Amaury Forgeot d'Arcfb1a5eb2008-09-11 21:03:37 +000023import itertools
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000024
25class RecursiveBlowup1:
26 def __init__(self):
27 self.__init__()
28
29def test_init():
30 return RecursiveBlowup1()
31
32class RecursiveBlowup2:
33 def __repr__(self):
34 return repr(self)
35
36def test_repr():
37 return repr(RecursiveBlowup2())
38
39class RecursiveBlowup4:
40 def __add__(self, x):
41 return x + self
42
43def test_add():
44 return RecursiveBlowup4() + RecursiveBlowup4()
45
46class RecursiveBlowup5:
47 def __getattr__(self, attr):
48 return getattr(self, attr)
49
50def test_getattr():
51 return RecursiveBlowup5().attr
52
53class RecursiveBlowup6:
54 def __getitem__(self, item):
55 return self[item - 2] + self[item - 1]
56
57def test_getitem():
58 return RecursiveBlowup6()[5]
Tim Peters182b5ac2004-07-18 06:16:08 +000059
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000060def test_recurse():
61 return test_recurse()
62
Amaury Forgeot d'Arcfb1a5eb2008-09-11 21:03:37 +000063def test_cpickle(_cache={}):
64 import io
65 try:
66 import _pickle
67 except ImportError:
68 print("cannot import _pickle, skipped!")
69 return
70 l = None
71 for n in itertools.count():
72 try:
73 l = _cache[n]
74 continue # Already tried and it works, let's save some time
75 except KeyError:
76 for i in range(100):
77 l = [l]
78 _pickle.Pickler(io.BytesIO(), protocol=-1).dump(l)
79 _cache[n] = l
80
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000081def check_limit(n, test_func_name):
82 sys.setrecursionlimit(n)
83 if test_func_name.startswith("test_"):
Collin Wintere7bf59f2007-08-30 18:39:28 +000084 print(test_func_name[5:])
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000085 else:
Collin Wintere7bf59f2007-08-30 18:39:28 +000086 print(test_func_name)
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000087 test_func = globals()[test_func_name]
88 try:
89 test_func()
90 except RuntimeError:
91 pass
92 else:
Collin Wintere7bf59f2007-08-30 18:39:28 +000093 print("Yikes!")
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +000094
95limit = 1000
96while 1:
97 check_limit(limit, "test_recurse")
98 check_limit(limit, "test_add")
99 check_limit(limit, "test_repr")
100 check_limit(limit, "test_init")
101 check_limit(limit, "test_getattr")
102 check_limit(limit, "test_getitem")
Amaury Forgeot d'Arcfb1a5eb2008-09-11 21:03:37 +0000103 check_limit(limit, "test_cpickle")
Collin Wintere7bf59f2007-08-30 18:39:28 +0000104 print("Limit of %d is fine" % limit)
Jeremy Hyltonc18b7d92000-08-31 19:24:17 +0000105 limit = limit + 100