blob: 8d221232eb6ce7d23565628d4c91b42a4fbef808 [file] [log] [blame]
Victor Stinner3844fe52015-09-26 10:38:01 +02001import os
2import re
3import sys
4import warnings
5from inspect import isabstract
6from test import support
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +00007try:
8 from _abc import _get_dump
9except ImportError:
Victor Stinner79b5d292019-04-09 01:36:34 +020010 import weakref
11
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000012 def _get_dump(cls):
Victor Stinner79b5d292019-04-09 01:36:34 +020013 # Reimplement _get_dump() for pure-Python implementation of
14 # the abc module (Lib/_py_abc.py)
15 registry_weakrefs = set(weakref.ref(obj) for obj in cls._abc_registry)
16 return (registry_weakrefs, cls._abc_cache,
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000017 cls._abc_negative_cache, cls._abc_negative_cache_version)
Victor Stinner3844fe52015-09-26 10:38:01 +020018
19
Victor Stinner4d299832019-04-26 04:08:53 +020020def dash_R(ns, test_name, test_func):
Victor Stinner3844fe52015-09-26 10:38:01 +020021 """Run a test multiple times, looking for reference leaks.
22
23 Returns:
24 False if the test didn't leak references; True if we detected refleaks.
25 """
26 # This code is hackish and inelegant, but it seems to do the job.
27 import copyreg
28 import collections.abc
29
30 if not hasattr(sys, 'gettotalrefcount'):
31 raise Exception("Tracking reference leaks requires a debug build "
32 "of Python")
33
Victor Stinner5aaac942019-04-09 14:23:47 +020034 # Avoid false positives due to various caches
35 # filling slowly with random data:
36 warm_caches()
37
Victor Stinner3844fe52015-09-26 10:38:01 +020038 # Save current values for dash_R_cleanup() to restore.
39 fs = warnings.filters[:]
40 ps = copyreg.dispatch_table.copy()
41 pic = sys.path_importer_cache.copy()
42 try:
43 import zipimport
44 except ImportError:
45 zdc = None # Run unmodified on platforms without zipimport support
46 else:
47 zdc = zipimport._zip_directory_cache.copy()
48 abcs = {}
49 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
50 if not isabstract(abc):
51 continue
52 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000053 abcs[obj] = _get_dump(obj)[0]
Victor Stinner3844fe52015-09-26 10:38:01 +020054
Victor Stinner6c2feab2017-09-01 13:05:27 +020055 # bpo-31217: Integer pool to get a single integer object for the same
56 # value. The pool is used to prevent false alarm when checking for memory
57 # block leaks. Fill the pool with values in -1000..1000 which are the most
58 # common (reference, memory block, file descriptor) differences.
59 int_pool = {value: value for value in range(-1000, 1000)}
60 def get_pooled_int(value):
61 return int_pool.setdefault(value, value)
62
Victor Stinner5aaac942019-04-09 14:23:47 +020063 nwarmup, ntracked, fname = ns.huntrleaks
Victor Stinner3844fe52015-09-26 10:38:01 +020064 fname = os.path.join(support.SAVEDCWD, fname)
65 repcount = nwarmup + ntracked
Victor Stinner5aaac942019-04-09 14:23:47 +020066
67 # Pre-allocate to ensure that the loop doesn't allocate anything new
68 rep_range = list(range(repcount))
Victor Stinner3844fe52015-09-26 10:38:01 +020069 rc_deltas = [0] * repcount
70 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020071 fd_deltas = [0] * repcount
Victor Stinner5aaac942019-04-09 14:23:47 +020072 getallocatedblocks = sys.getallocatedblocks
73 gettotalrefcount = sys.gettotalrefcount
74 fd_count = support.fd_count
Victor Stinner3844fe52015-09-26 10:38:01 +020075
Victor Stinner9a142142015-09-30 13:51:17 +020076 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020077 rc_before = alloc_before = fd_before = 0
Victor Stinner5aaac942019-04-09 14:23:47 +020078
79 if not ns.quiet:
80 print("beginning", repcount, "repetitions", file=sys.stderr)
81 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
82 flush=True)
83
Victor Stinnerbb444782019-04-09 18:26:16 +020084 dash_R_cleanup(fs, ps, pic, zdc, abcs)
85
Victor Stinner5aaac942019-04-09 14:23:47 +020086 for i in rep_range:
87 test_func()
88 dash_R_cleanup(fs, ps, pic, zdc, abcs)
89
Victor Stinnerbb444782019-04-09 18:26:16 +020090 # dash_R_cleanup() ends with collecting cyclic trash:
91 # read memory statistics immediately after.
Victor Stinner5aaac942019-04-09 14:23:47 +020092 alloc_after = getallocatedblocks()
93 rc_after = gettotalrefcount()
94 fd_after = fd_count()
95
96 if not ns.quiet:
97 print('.', end='', file=sys.stderr, flush=True)
98
99 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
100 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
101 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
102
Victor Stinner076fc872015-10-03 00:20:56 +0200103 alloc_before = alloc_after
104 rc_before = rc_after
105 fd_before = fd_after
Victor Stinner5aaac942019-04-09 14:23:47 +0200106
107 if not ns.quiet:
108 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +0200109
Victor Stinner3844fe52015-09-26 10:38:01 +0200110 # These checkers return False on success, True on failure
111 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200112 # Checker for reference counters and memomry blocks.
113 #
Victor Stinner48b5c422017-06-27 02:02:04 +0200114 # bpo-30776: Try to ignore false positives:
115 #
116 # [3, 0, 0]
117 # [0, 1, 0]
118 # [8, -8, 1]
119 #
120 # Expected leaks:
121 #
122 # [5, 5, 6]
123 # [10, 1, 1]
124 return all(delta >= 1 for delta in deltas)
125
Victor Stinner48b5c422017-06-27 02:02:04 +0200126 def check_fd_deltas(deltas):
127 return any(deltas)
128
Victor Stinner3844fe52015-09-26 10:38:01 +0200129 failed = False
130 for deltas, item_name, checker in [
131 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200132 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +0200133 (fd_deltas, 'file descriptors', check_fd_deltas)
134 ]:
135 # ignore warmup runs
136 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200137 if checker(deltas):
138 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner5aaac942019-04-09 14:23:47 +0200139 test_name, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200140 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200141 with open(fname, "a") as refrep:
142 print(msg, file=refrep)
143 refrep.flush()
144 failed = True
145 return failed
146
147
148def dash_R_cleanup(fs, ps, pic, zdc, abcs):
Victor Stinner5aaac942019-04-09 14:23:47 +0200149 import copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200150 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200151
Victor Stinner3844fe52015-09-26 10:38:01 +0200152 # Restore some original values.
153 warnings.filters[:] = fs
154 copyreg.dispatch_table.clear()
155 copyreg.dispatch_table.update(ps)
156 sys.path_importer_cache.clear()
157 sys.path_importer_cache.update(pic)
158 try:
159 import zipimport
160 except ImportError:
161 pass # Run unmodified on platforms without zipimport support
162 else:
163 zipimport._zip_directory_cache.clear()
164 zipimport._zip_directory_cache.update(zdc)
165
166 # clear type cache
167 sys._clear_type_cache()
168
169 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100170 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
171 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100172 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200173 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000174 for ref in abcs.get(obj, set()):
175 if ref() is not None:
176 obj.register(ref())
177 obj._abc_caches_clear()
Victor Stinner3844fe52015-09-26 10:38:01 +0200178
Serhiy Storchaka83910262016-11-11 11:46:44 +0200179 clear_caches()
180
Serhiy Storchaka83910262016-11-11 11:46:44 +0200181
182def clear_caches():
Serhiy Storchaka83910262016-11-11 11:46:44 +0200183 # Clear the warnings registry, so they can be displayed again
184 for mod in sys.modules.values():
185 if hasattr(mod, '__warningregistry__'):
186 del mod.__warningregistry__
187
Victor Stinner3844fe52015-09-26 10:38:01 +0200188 # Flush standard output, so that buffered data is sent to the OS and
189 # associated Python objects are reclaimed.
190 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
191 if stream is not None:
192 stream.flush()
193
194 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200195 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200196 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200197 distutils_dir_util = sys.modules['distutils.dir_util']
198 except KeyError:
199 pass
200 else:
201 distutils_dir_util._path_created.clear()
202 re.purge()
203
204 try:
205 _strptime = sys.modules['_strptime']
206 except KeyError:
207 pass
208 else:
209 _strptime._regex_cache.clear()
210
211 try:
212 urllib_parse = sys.modules['urllib.parse']
213 except KeyError:
214 pass
215 else:
216 urllib_parse.clear_cache()
217
218 try:
219 urllib_request = sys.modules['urllib.request']
220 except KeyError:
221 pass
222 else:
223 urllib_request.urlcleanup()
224
225 try:
226 linecache = sys.modules['linecache']
227 except KeyError:
228 pass
229 else:
230 linecache.clearcache()
231
232 try:
233 mimetypes = sys.modules['mimetypes']
234 except KeyError:
235 pass
236 else:
237 mimetypes._default_mime_types()
238
239 try:
240 filecmp = sys.modules['filecmp']
241 except KeyError:
242 pass
243 else:
244 filecmp._cache.clear()
245
246 try:
247 struct = sys.modules['struct']
248 except KeyError:
249 pass
250 else:
251 struct._clearcache()
252
253 try:
254 doctest = sys.modules['doctest']
255 except KeyError:
256 pass
257 else:
258 doctest.master = None
259
260 try:
261 ctypes = sys.modules['ctypes']
262 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200263 pass
264 else:
265 ctypes._reset_cache()
266
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200267 try:
268 typing = sys.modules['typing']
269 except KeyError:
270 pass
271 else:
272 for f in typing._cleanups:
273 f()
274
Victor Stinner5aaac942019-04-09 14:23:47 +0200275 support.gc_collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200276
277
278def warm_caches():
279 # char cache
280 s = bytes(range(256))
281 for i in range(256):
282 s[i:i+1]
283 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200284 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200285 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200286 list(range(-5, 257))