blob: d68ea63b5b3c1385072fb28788646640cfaccc29 [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
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +00008try:
9 from _abc import _get_dump
10except ImportError:
Victor Stinner79b5d292019-04-09 01:36:34 +020011 import weakref
12
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000013 def _get_dump(cls):
Victor Stinner79b5d292019-04-09 01:36:34 +020014 # Reimplement _get_dump() for pure-Python implementation of
15 # the abc module (Lib/_py_abc.py)
16 registry_weakrefs = set(weakref.ref(obj) for obj in cls._abc_registry)
17 return (registry_weakrefs, cls._abc_cache,
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000018 cls._abc_negative_cache, cls._abc_negative_cache_version)
Victor Stinner3844fe52015-09-26 10:38:01 +020019
20
21def dash_R(the_module, test, indirect_test, huntrleaks):
22 """Run a test multiple times, looking for reference leaks.
23
24 Returns:
25 False if the test didn't leak references; True if we detected refleaks.
26 """
27 # This code is hackish and inelegant, but it seems to do the job.
28 import copyreg
29 import collections.abc
30
31 if not hasattr(sys, 'gettotalrefcount'):
32 raise Exception("Tracking reference leaks requires a debug build "
33 "of Python")
34
35 # Save current values for dash_R_cleanup() to restore.
36 fs = warnings.filters[:]
37 ps = copyreg.dispatch_table.copy()
38 pic = sys.path_importer_cache.copy()
39 try:
40 import zipimport
41 except ImportError:
42 zdc = None # Run unmodified on platforms without zipimport support
43 else:
44 zdc = zipimport._zip_directory_cache.copy()
45 abcs = {}
46 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
47 if not isabstract(abc):
48 continue
49 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000050 abcs[obj] = _get_dump(obj)[0]
Victor Stinner3844fe52015-09-26 10:38:01 +020051
Victor Stinner6c2feab2017-09-01 13:05:27 +020052 # bpo-31217: Integer pool to get a single integer object for the same
53 # value. The pool is used to prevent false alarm when checking for memory
54 # block leaks. Fill the pool with values in -1000..1000 which are the most
55 # common (reference, memory block, file descriptor) differences.
56 int_pool = {value: value for value in range(-1000, 1000)}
57 def get_pooled_int(value):
58 return int_pool.setdefault(value, value)
59
Victor Stinner3844fe52015-09-26 10:38:01 +020060 nwarmup, ntracked, fname = huntrleaks
61 fname = os.path.join(support.SAVEDCWD, fname)
62 repcount = nwarmup + ntracked
63 rc_deltas = [0] * repcount
64 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020065 fd_deltas = [0] * repcount
Victor Stinner3844fe52015-09-26 10:38:01 +020066
67 print("beginning", repcount, "repetitions", file=sys.stderr)
Victor Stinnerf33536c2015-09-30 00:48:27 +020068 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
69 flush=True)
Victor Stinner9a142142015-09-30 13:51:17 +020070 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020071 rc_before = alloc_before = fd_before = 0
Victor Stinner3844fe52015-09-26 10:38:01 +020072 for i in range(repcount):
73 indirect_test()
Victor Stinner076fc872015-10-03 00:20:56 +020074 alloc_after, rc_after, fd_after = dash_R_cleanup(fs, ps, pic, zdc,
75 abcs)
Victor Stinner17a63e22017-02-08 13:06:08 +010076 print('.', end='', file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +020077 if i >= nwarmup:
Victor Stinner6c2feab2017-09-01 13:05:27 +020078 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
79 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
80 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
Victor Stinner076fc872015-10-03 00:20:56 +020081 alloc_before = alloc_after
82 rc_before = rc_after
83 fd_before = fd_after
Victor Stinner3844fe52015-09-26 10:38:01 +020084 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +020085
Victor Stinner3844fe52015-09-26 10:38:01 +020086 # These checkers return False on success, True on failure
87 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +020088 # Checker for reference counters and memomry blocks.
89 #
Victor Stinner48b5c422017-06-27 02:02:04 +020090 # bpo-30776: Try to ignore false positives:
91 #
92 # [3, 0, 0]
93 # [0, 1, 0]
94 # [8, -8, 1]
95 #
96 # Expected leaks:
97 #
98 # [5, 5, 6]
99 # [10, 1, 1]
100 return all(delta >= 1 for delta in deltas)
101
Victor Stinner48b5c422017-06-27 02:02:04 +0200102 def check_fd_deltas(deltas):
103 return any(deltas)
104
Victor Stinner3844fe52015-09-26 10:38:01 +0200105 failed = False
106 for deltas, item_name, checker in [
107 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200108 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +0200109 (fd_deltas, 'file descriptors', check_fd_deltas)
110 ]:
111 # ignore warmup runs
112 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200113 if checker(deltas):
114 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner48b5c422017-06-27 02:02:04 +0200115 test, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200116 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200117 with open(fname, "a") as refrep:
118 print(msg, file=refrep)
119 refrep.flush()
120 failed = True
121 return failed
122
123
124def dash_R_cleanup(fs, ps, pic, zdc, abcs):
125 import gc, copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200126 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200127
Victor Stinner3844fe52015-09-26 10:38:01 +0200128 # Restore some original values.
129 warnings.filters[:] = fs
130 copyreg.dispatch_table.clear()
131 copyreg.dispatch_table.update(ps)
132 sys.path_importer_cache.clear()
133 sys.path_importer_cache.update(pic)
134 try:
135 import zipimport
136 except ImportError:
137 pass # Run unmodified on platforms without zipimport support
138 else:
139 zipimport._zip_directory_cache.clear()
140 zipimport._zip_directory_cache.update(zdc)
141
142 # clear type cache
143 sys._clear_type_cache()
144
145 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100146 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
147 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100148 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200149 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000150 for ref in abcs.get(obj, set()):
151 if ref() is not None:
152 obj.register(ref())
153 obj._abc_caches_clear()
Victor Stinner3844fe52015-09-26 10:38:01 +0200154
Serhiy Storchaka83910262016-11-11 11:46:44 +0200155 clear_caches()
156
157 # Collect cyclic trash and read memory statistics immediately after.
158 func1 = sys.getallocatedblocks
159 func2 = sys.gettotalrefcount
160 gc.collect()
Antoine Pitrou896145d2017-07-22 13:22:54 +0200161 return func1(), func2(), support.fd_count()
Serhiy Storchaka83910262016-11-11 11:46:44 +0200162
163
164def clear_caches():
165 import gc
166
167 # Clear the warnings registry, so they can be displayed again
168 for mod in sys.modules.values():
169 if hasattr(mod, '__warningregistry__'):
170 del mod.__warningregistry__
171
Victor Stinner3844fe52015-09-26 10:38:01 +0200172 # Flush standard output, so that buffered data is sent to the OS and
173 # associated Python objects are reclaimed.
174 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
175 if stream is not None:
176 stream.flush()
177
178 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200179 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200180 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200181 distutils_dir_util = sys.modules['distutils.dir_util']
182 except KeyError:
183 pass
184 else:
185 distutils_dir_util._path_created.clear()
186 re.purge()
187
188 try:
189 _strptime = sys.modules['_strptime']
190 except KeyError:
191 pass
192 else:
193 _strptime._regex_cache.clear()
194
195 try:
196 urllib_parse = sys.modules['urllib.parse']
197 except KeyError:
198 pass
199 else:
200 urllib_parse.clear_cache()
201
202 try:
203 urllib_request = sys.modules['urllib.request']
204 except KeyError:
205 pass
206 else:
207 urllib_request.urlcleanup()
208
209 try:
210 linecache = sys.modules['linecache']
211 except KeyError:
212 pass
213 else:
214 linecache.clearcache()
215
216 try:
217 mimetypes = sys.modules['mimetypes']
218 except KeyError:
219 pass
220 else:
221 mimetypes._default_mime_types()
222
223 try:
224 filecmp = sys.modules['filecmp']
225 except KeyError:
226 pass
227 else:
228 filecmp._cache.clear()
229
230 try:
231 struct = sys.modules['struct']
232 except KeyError:
233 pass
234 else:
235 struct._clearcache()
236
237 try:
238 doctest = sys.modules['doctest']
239 except KeyError:
240 pass
241 else:
242 doctest.master = None
243
244 try:
245 ctypes = sys.modules['ctypes']
246 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200247 pass
248 else:
249 ctypes._reset_cache()
250
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200251 try:
252 typing = sys.modules['typing']
253 except KeyError:
254 pass
255 else:
256 for f in typing._cleanups:
257 f()
258
Victor Stinner3844fe52015-09-26 10:38:01 +0200259 gc.collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200260
261
262def warm_caches():
263 # char cache
264 s = bytes(range(256))
265 for i in range(256):
266 s[i:i+1]
267 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200268 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200269 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200270 list(range(-5, 257))