annotate Tools/scripts/find_recursionlimit.py @ 58689:514b56efd89a 3.1

Merged revisions 77962 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77962 | r.david.murray | 2010-02-04 11:41:57 -0500 (Thu, 04 Feb 2010) | 17 lines Merged revisions 77943,77959-77960 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77943 | r.david.murray | 2010-02-03 08:36:23 -0500 (Wed, 03 Feb 2010) | 2 lines Explicitly mention the default value for formatdate's usegmt parameter. ........ r77959 | nick.coghlan | 2010-02-04 07:43:58 -0500 (Thu, 04 Feb 2010) | 1 line Issue 6760: Clarify args handling for subprocess.Popen. Patch by Chris Rebert ........ r77960 | r.david.murray | 2010-02-04 11:33:31 -0500 (Thu, 04 Feb 2010) | 2 lines Add Chris Rebert to ACKS for issue 6760 Popen doc improvements. ........ ................
author R. David Murray <rdmurray@bitdance.com>
date Thu, 04 Feb 2010 16:44:31 +0000
parents 029d69659b5f
children bcf030f73eee fcfe324663a6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
56889
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1 #! /usr/bin/env python
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
2 """Find the maximum recursion limit that prevents interpreter termination.
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
3
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
4 This script finds the maximum safe recursion limit on a particular
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
5 platform. If you need to change the recursion limit on your system,
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
6 this script will tell you a safe upper bound. To use the new limit,
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
7 call sys.setrecursionlimit().
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
8
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
9 This module implements several ways to create infinite recursion in
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
10 Python. Different implementations end up pushing different numbers of
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
11 C stack frames, depending on how many calls through Python's abstract
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
12 C API occur.
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
13
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
14 After each round of tests, it prints a message:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
15 "Limit of NNNN is fine".
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
16
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
17 The highest printed value of "NNNN" is therefore the highest potentially
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
18 safe limit for your system (which depends on the OS, architecture, but also
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
19 the compilation flags). Please note that it is practically impossible to
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
20 test all possible recursion paths in the interpreter, so the results of
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
21 this test should not be trusted blindly -- although they give a good hint
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
22 of which values are reasonable.
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
23
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
24 NOTE: When the C stack space allocated by your system is exceeded due
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
25 to excessive recursion, exact behaviour depends on the platform, although
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
26 the interpreter will always fail in a likely brutal way: either a
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
27 segmentation fault, a MemoryError, or just a silent abort.
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
28
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
29 NB: A program that does not use __methods__ can set a higher limit.
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
30 """
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
31
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
32 import sys
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
33 import itertools
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
34
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
35 class RecursiveBlowup1:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
36 def __init__(self):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
37 self.__init__()
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
38
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
39 def test_init():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
40 return RecursiveBlowup1()
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
41
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
42 class RecursiveBlowup2:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
43 def __repr__(self):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
44 return repr(self)
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
45
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
46 def test_repr():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
47 return repr(RecursiveBlowup2())
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
48
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
49 class RecursiveBlowup4:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
50 def __add__(self, x):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
51 return x + self
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
52
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
53 def test_add():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
54 return RecursiveBlowup4() + RecursiveBlowup4()
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
55
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
56 class RecursiveBlowup5:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
57 def __getattr__(self, attr):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
58 return getattr(self, attr)
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
59
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
60 def test_getattr():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
61 return RecursiveBlowup5().attr
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
62
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
63 class RecursiveBlowup6:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
64 def __getitem__(self, item):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
65 return self[item - 2] + self[item - 1]
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
66
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
67 def test_getitem():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
68 return RecursiveBlowup6()[5]
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
69
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
70 def test_recurse():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
71 return test_recurse()
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
72
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
73 def test_cpickle(_cache={}):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
74 import io
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
75 try:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
76 import _pickle
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
77 except ImportError:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
78 print("cannot import _pickle, skipped!")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
79 return
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
80 l = None
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
81 for n in itertools.count():
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
82 try:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
83 l = _cache[n]
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
84 continue # Already tried and it works, let's save some time
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
85 except KeyError:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
86 for i in range(100):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
87 l = [l]
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
88 _pickle.Pickler(io.BytesIO(), protocol=-1).dump(l)
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
89 _cache[n] = l
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
90
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
91 def check_limit(n, test_func_name):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
92 sys.setrecursionlimit(n)
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
93 if test_func_name.startswith("test_"):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
94 print(test_func_name[5:])
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
95 else:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
96 print(test_func_name)
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
97 test_func = globals()[test_func_name]
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
98 try:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
99 test_func()
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
100 # AttributeError can be raised because of the way e.g. PyDict_GetItem()
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
101 # silences all exceptions and returns NULL, which is usually interpreted
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
102 # as "missing attribute".
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
103 except (RuntimeError, AttributeError):
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
104 pass
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
105 else:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
106 print("Yikes!")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
107
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
108 limit = 1000
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
109 while 1:
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
110 check_limit(limit, "test_recurse")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
111 check_limit(limit, "test_add")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
112 check_limit(limit, "test_repr")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
113 check_limit(limit, "test_init")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
114 check_limit(limit, "test_getattr")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
115 check_limit(limit, "test_getitem")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
116 check_limit(limit, "test_cpickle")
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
117 print("Limit of %d is fine" % limit)
029d69659b5f Merged revisions 75373 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
118 limit = limit + 100