blob: 2ca9aa87644c0de7173da0b8359e8efe6b48d7bf [file] [log] [blame]
Victor Stinner076fc872015-10-03 00:20:56 +02001import errno
Victor Stinner3844fe52015-09-26 10:38:01 +02002import os
3import re
4import sys
5import warnings
6from inspect import isabstract
7from test import support
8
9
10def dash_R(the_module, test, indirect_test, huntrleaks):
11 """Run a test multiple times, looking for reference leaks.
12
13 Returns:
14 False if the test didn't leak references; True if we detected refleaks.
15 """
16 # This code is hackish and inelegant, but it seems to do the job.
17 import copyreg
18 import collections.abc
19
20 if not hasattr(sys, 'gettotalrefcount'):
21 raise Exception("Tracking reference leaks requires a debug build "
22 "of Python")
23
24 # Save current values for dash_R_cleanup() to restore.
25 fs = warnings.filters[:]
26 ps = copyreg.dispatch_table.copy()
27 pic = sys.path_importer_cache.copy()
28 try:
29 import zipimport
30 except ImportError:
31 zdc = None # Run unmodified on platforms without zipimport support
32 else:
33 zdc = zipimport._zip_directory_cache.copy()
34 abcs = {}
35 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
36 if not isabstract(abc):
37 continue
38 for obj in abc.__subclasses__() + [abc]:
39 abcs[obj] = obj._abc_registry.copy()
40
Victor Stinner6c2feab2017-09-01 13:05:27 +020041 # bpo-31217: Integer pool to get a single integer object for the same
42 # value. The pool is used to prevent false alarm when checking for memory
43 # block leaks. Fill the pool with values in -1000..1000 which are the most
44 # common (reference, memory block, file descriptor) differences.
45 int_pool = {value: value for value in range(-1000, 1000)}
46 def get_pooled_int(value):
47 return int_pool.setdefault(value, value)
48
Victor Stinner3844fe52015-09-26 10:38:01 +020049 nwarmup, ntracked, fname = huntrleaks
50 fname = os.path.join(support.SAVEDCWD, fname)
51 repcount = nwarmup + ntracked
52 rc_deltas = [0] * repcount
53 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020054 fd_deltas = [0] * repcount
Victor Stinner3844fe52015-09-26 10:38:01 +020055
56 print("beginning", repcount, "repetitions", file=sys.stderr)
Victor Stinnerf33536c2015-09-30 00:48:27 +020057 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
58 flush=True)
Victor Stinner9a142142015-09-30 13:51:17 +020059 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020060 rc_before = alloc_before = fd_before = 0
Victor Stinner3844fe52015-09-26 10:38:01 +020061 for i in range(repcount):
62 indirect_test()
Victor Stinner076fc872015-10-03 00:20:56 +020063 alloc_after, rc_after, fd_after = dash_R_cleanup(fs, ps, pic, zdc,
64 abcs)
Victor Stinner17a63e22017-02-08 13:06:08 +010065 print('.', end='', file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +020066 if i >= nwarmup:
Victor Stinner6c2feab2017-09-01 13:05:27 +020067 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
68 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
69 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
Victor Stinner076fc872015-10-03 00:20:56 +020070 alloc_before = alloc_after
71 rc_before = rc_after
72 fd_before = fd_after
Victor Stinner3844fe52015-09-26 10:38:01 +020073 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +020074
Victor Stinner3844fe52015-09-26 10:38:01 +020075 # These checkers return False on success, True on failure
76 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +020077 # Checker for reference counters and memomry blocks.
78 #
Victor Stinner48b5c422017-06-27 02:02:04 +020079 # bpo-30776: Try to ignore false positives:
80 #
81 # [3, 0, 0]
82 # [0, 1, 0]
83 # [8, -8, 1]
84 #
85 # Expected leaks:
86 #
87 # [5, 5, 6]
88 # [10, 1, 1]
89 return all(delta >= 1 for delta in deltas)
90
Victor Stinner48b5c422017-06-27 02:02:04 +020091 def check_fd_deltas(deltas):
92 return any(deltas)
93
Victor Stinner3844fe52015-09-26 10:38:01 +020094 failed = False
95 for deltas, item_name, checker in [
96 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +020097 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +020098 (fd_deltas, 'file descriptors', check_fd_deltas)
99 ]:
100 # ignore warmup runs
101 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200102 if checker(deltas):
103 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner48b5c422017-06-27 02:02:04 +0200104 test, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200105 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200106 with open(fname, "a") as refrep:
107 print(msg, file=refrep)
108 refrep.flush()
109 failed = True
110 return failed
111
112
113def dash_R_cleanup(fs, ps, pic, zdc, abcs):
114 import gc, copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200115 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200116 from weakref import WeakSet
117
Victor Stinner3844fe52015-09-26 10:38:01 +0200118 # Restore some original values.
119 warnings.filters[:] = fs
120 copyreg.dispatch_table.clear()
121 copyreg.dispatch_table.update(ps)
122 sys.path_importer_cache.clear()
123 sys.path_importer_cache.update(pic)
124 try:
125 import zipimport
126 except ImportError:
127 pass # Run unmodified on platforms without zipimport support
128 else:
129 zipimport._zip_directory_cache.clear()
130 zipimport._zip_directory_cache.update(zdc)
131
132 # clear type cache
133 sys._clear_type_cache()
134
135 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100136 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
137 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100138 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200139 for obj in abc.__subclasses__() + [abc]:
140 obj._abc_registry = abcs.get(obj, WeakSet()).copy()
141 obj._abc_cache.clear()
142 obj._abc_negative_cache.clear()
143
Serhiy Storchaka83910262016-11-11 11:46:44 +0200144 clear_caches()
145
146 # Collect cyclic trash and read memory statistics immediately after.
147 func1 = sys.getallocatedblocks
148 func2 = sys.gettotalrefcount
149 gc.collect()
Antoine Pitrou896145d2017-07-22 13:22:54 +0200150 return func1(), func2(), support.fd_count()
Serhiy Storchaka83910262016-11-11 11:46:44 +0200151
152
153def clear_caches():
154 import gc
155
156 # Clear the warnings registry, so they can be displayed again
157 for mod in sys.modules.values():
158 if hasattr(mod, '__warningregistry__'):
159 del mod.__warningregistry__
160
Victor Stinner3844fe52015-09-26 10:38:01 +0200161 # Flush standard output, so that buffered data is sent to the OS and
162 # associated Python objects are reclaimed.
163 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
164 if stream is not None:
165 stream.flush()
166
167 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200168 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200169 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200170 distutils_dir_util = sys.modules['distutils.dir_util']
171 except KeyError:
172 pass
173 else:
174 distutils_dir_util._path_created.clear()
175 re.purge()
176
177 try:
178 _strptime = sys.modules['_strptime']
179 except KeyError:
180 pass
181 else:
182 _strptime._regex_cache.clear()
183
184 try:
185 urllib_parse = sys.modules['urllib.parse']
186 except KeyError:
187 pass
188 else:
189 urllib_parse.clear_cache()
190
191 try:
192 urllib_request = sys.modules['urllib.request']
193 except KeyError:
194 pass
195 else:
196 urllib_request.urlcleanup()
197
198 try:
199 linecache = sys.modules['linecache']
200 except KeyError:
201 pass
202 else:
203 linecache.clearcache()
204
205 try:
206 mimetypes = sys.modules['mimetypes']
207 except KeyError:
208 pass
209 else:
210 mimetypes._default_mime_types()
211
212 try:
213 filecmp = sys.modules['filecmp']
214 except KeyError:
215 pass
216 else:
217 filecmp._cache.clear()
218
219 try:
220 struct = sys.modules['struct']
221 except KeyError:
222 pass
223 else:
224 struct._clearcache()
225
226 try:
227 doctest = sys.modules['doctest']
228 except KeyError:
229 pass
230 else:
231 doctest.master = None
232
233 try:
234 ctypes = sys.modules['ctypes']
235 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200236 pass
237 else:
238 ctypes._reset_cache()
239
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200240 try:
241 typing = sys.modules['typing']
242 except KeyError:
243 pass
244 else:
245 for f in typing._cleanups:
246 f()
247
Victor Stinner3844fe52015-09-26 10:38:01 +0200248 gc.collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200249
250
251def warm_caches():
252 # char cache
253 s = bytes(range(256))
254 for i in range(256):
255 s[i:i+1]
256 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200257 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200258 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200259 list(range(-5, 257))