blob: 0bb8a0a2bf083cf4ed5d239888ec7d930631ba26 [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
Victor Stinner5aaac942019-04-09 14:23:47 +020021def dash_R(ns, the_module, test_name, test_func):
Victor Stinner3844fe52015-09-26 10:38:01 +020022 """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
Victor Stinner5aaac942019-04-09 14:23:47 +020035 # Avoid false positives due to various caches
36 # filling slowly with random data:
37 warm_caches()
38
Victor Stinner3844fe52015-09-26 10:38:01 +020039 # Save current values for dash_R_cleanup() to restore.
40 fs = warnings.filters[:]
41 ps = copyreg.dispatch_table.copy()
42 pic = sys.path_importer_cache.copy()
43 try:
44 import zipimport
45 except ImportError:
46 zdc = None # Run unmodified on platforms without zipimport support
47 else:
48 zdc = zipimport._zip_directory_cache.copy()
49 abcs = {}
50 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
51 if not isabstract(abc):
52 continue
53 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000054 abcs[obj] = _get_dump(obj)[0]
Victor Stinner3844fe52015-09-26 10:38:01 +020055
Victor Stinner6c2feab2017-09-01 13:05:27 +020056 # bpo-31217: Integer pool to get a single integer object for the same
57 # value. The pool is used to prevent false alarm when checking for memory
58 # block leaks. Fill the pool with values in -1000..1000 which are the most
59 # common (reference, memory block, file descriptor) differences.
60 int_pool = {value: value for value in range(-1000, 1000)}
61 def get_pooled_int(value):
62 return int_pool.setdefault(value, value)
63
Victor Stinner5aaac942019-04-09 14:23:47 +020064 nwarmup, ntracked, fname = ns.huntrleaks
Victor Stinner3844fe52015-09-26 10:38:01 +020065 fname = os.path.join(support.SAVEDCWD, fname)
66 repcount = nwarmup + ntracked
Victor Stinner5aaac942019-04-09 14:23:47 +020067
68 # Pre-allocate to ensure that the loop doesn't allocate anything new
69 rep_range = list(range(repcount))
Victor Stinner3844fe52015-09-26 10:38:01 +020070 rc_deltas = [0] * repcount
71 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020072 fd_deltas = [0] * repcount
Victor Stinner5aaac942019-04-09 14:23:47 +020073 getallocatedblocks = sys.getallocatedblocks
74 gettotalrefcount = sys.gettotalrefcount
75 fd_count = support.fd_count
Victor Stinner3844fe52015-09-26 10:38:01 +020076
Victor Stinner9a142142015-09-30 13:51:17 +020077 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020078 rc_before = alloc_before = fd_before = 0
Victor Stinner5aaac942019-04-09 14:23:47 +020079
80 if not ns.quiet:
81 print("beginning", repcount, "repetitions", file=sys.stderr)
82 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
83 flush=True)
84
85 for i in rep_range:
86 test_func()
87 dash_R_cleanup(fs, ps, pic, zdc, abcs)
88
89 # Collect cyclic trash and read memory statistics immediately after.
90 support.gc_collect()
91 alloc_after = getallocatedblocks()
92 rc_after = gettotalrefcount()
93 fd_after = fd_count()
94
95 if not ns.quiet:
96 print('.', end='', file=sys.stderr, flush=True)
97
98 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
99 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
100 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
101
Victor Stinner076fc872015-10-03 00:20:56 +0200102 alloc_before = alloc_after
103 rc_before = rc_after
104 fd_before = fd_after
Victor Stinner5aaac942019-04-09 14:23:47 +0200105
106 if not ns.quiet:
107 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +0200108
Victor Stinner3844fe52015-09-26 10:38:01 +0200109 # These checkers return False on success, True on failure
110 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200111 # Checker for reference counters and memomry blocks.
112 #
Victor Stinner48b5c422017-06-27 02:02:04 +0200113 # bpo-30776: Try to ignore false positives:
114 #
115 # [3, 0, 0]
116 # [0, 1, 0]
117 # [8, -8, 1]
118 #
119 # Expected leaks:
120 #
121 # [5, 5, 6]
122 # [10, 1, 1]
123 return all(delta >= 1 for delta in deltas)
124
Victor Stinner48b5c422017-06-27 02:02:04 +0200125 def check_fd_deltas(deltas):
126 return any(deltas)
127
Victor Stinner3844fe52015-09-26 10:38:01 +0200128 failed = False
129 for deltas, item_name, checker in [
130 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200131 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +0200132 (fd_deltas, 'file descriptors', check_fd_deltas)
133 ]:
134 # ignore warmup runs
135 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200136 if checker(deltas):
137 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner5aaac942019-04-09 14:23:47 +0200138 test_name, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200139 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200140 with open(fname, "a") as refrep:
141 print(msg, file=refrep)
142 refrep.flush()
143 failed = True
144 return failed
145
146
147def dash_R_cleanup(fs, ps, pic, zdc, abcs):
Victor Stinner5aaac942019-04-09 14:23:47 +0200148 import copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200149 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200150
Victor Stinner3844fe52015-09-26 10:38:01 +0200151 # Restore some original values.
152 warnings.filters[:] = fs
153 copyreg.dispatch_table.clear()
154 copyreg.dispatch_table.update(ps)
155 sys.path_importer_cache.clear()
156 sys.path_importer_cache.update(pic)
157 try:
158 import zipimport
159 except ImportError:
160 pass # Run unmodified on platforms without zipimport support
161 else:
162 zipimport._zip_directory_cache.clear()
163 zipimport._zip_directory_cache.update(zdc)
164
165 # clear type cache
166 sys._clear_type_cache()
167
168 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100169 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
170 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100171 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200172 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000173 for ref in abcs.get(obj, set()):
174 if ref() is not None:
175 obj.register(ref())
176 obj._abc_caches_clear()
Victor Stinner3844fe52015-09-26 10:38:01 +0200177
Serhiy Storchaka83910262016-11-11 11:46:44 +0200178 clear_caches()
179
Serhiy Storchaka83910262016-11-11 11:46:44 +0200180
181def clear_caches():
Serhiy Storchaka83910262016-11-11 11:46:44 +0200182 # Clear the warnings registry, so they can be displayed again
183 for mod in sys.modules.values():
184 if hasattr(mod, '__warningregistry__'):
185 del mod.__warningregistry__
186
Victor Stinner3844fe52015-09-26 10:38:01 +0200187 # Flush standard output, so that buffered data is sent to the OS and
188 # associated Python objects are reclaimed.
189 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
190 if stream is not None:
191 stream.flush()
192
193 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200194 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200195 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200196 distutils_dir_util = sys.modules['distutils.dir_util']
197 except KeyError:
198 pass
199 else:
200 distutils_dir_util._path_created.clear()
201 re.purge()
202
203 try:
204 _strptime = sys.modules['_strptime']
205 except KeyError:
206 pass
207 else:
208 _strptime._regex_cache.clear()
209
210 try:
211 urllib_parse = sys.modules['urllib.parse']
212 except KeyError:
213 pass
214 else:
215 urllib_parse.clear_cache()
216
217 try:
218 urllib_request = sys.modules['urllib.request']
219 except KeyError:
220 pass
221 else:
222 urllib_request.urlcleanup()
223
224 try:
225 linecache = sys.modules['linecache']
226 except KeyError:
227 pass
228 else:
229 linecache.clearcache()
230
231 try:
232 mimetypes = sys.modules['mimetypes']
233 except KeyError:
234 pass
235 else:
236 mimetypes._default_mime_types()
237
238 try:
239 filecmp = sys.modules['filecmp']
240 except KeyError:
241 pass
242 else:
243 filecmp._cache.clear()
244
245 try:
246 struct = sys.modules['struct']
247 except KeyError:
248 pass
249 else:
250 struct._clearcache()
251
252 try:
253 doctest = sys.modules['doctest']
254 except KeyError:
255 pass
256 else:
257 doctest.master = None
258
259 try:
260 ctypes = sys.modules['ctypes']
261 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200262 pass
263 else:
264 ctypes._reset_cache()
265
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200266 try:
267 typing = sys.modules['typing']
268 except KeyError:
269 pass
270 else:
271 for f in typing._cleanups:
272 f()
273
Victor Stinner5aaac942019-04-09 14:23:47 +0200274 support.gc_collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200275
276
277def warm_caches():
278 # char cache
279 s = bytes(range(256))
280 for i in range(256):
281 s[i:i+1]
282 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200283 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200284 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200285 list(range(-5, 257))