blob: 235d6bfd3af621d60e4ad21e1b1058b02ab3dbe0 [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
Victor Stinnerbb444782019-04-09 18:26:16 +020085 dash_R_cleanup(fs, ps, pic, zdc, abcs)
86
Victor Stinner5aaac942019-04-09 14:23:47 +020087 for i in rep_range:
88 test_func()
89 dash_R_cleanup(fs, ps, pic, zdc, abcs)
90
Victor Stinnerbb444782019-04-09 18:26:16 +020091 # dash_R_cleanup() ends with collecting cyclic trash:
92 # read memory statistics immediately after.
Victor Stinner5aaac942019-04-09 14:23:47 +020093 alloc_after = getallocatedblocks()
94 rc_after = gettotalrefcount()
95 fd_after = fd_count()
96
97 if not ns.quiet:
98 print('.', end='', file=sys.stderr, flush=True)
99
100 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
101 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
102 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
103
Victor Stinner076fc872015-10-03 00:20:56 +0200104 alloc_before = alloc_after
105 rc_before = rc_after
106 fd_before = fd_after
Victor Stinner5aaac942019-04-09 14:23:47 +0200107
108 if not ns.quiet:
109 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +0200110
Victor Stinner3844fe52015-09-26 10:38:01 +0200111 # These checkers return False on success, True on failure
112 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200113 # Checker for reference counters and memomry blocks.
114 #
Victor Stinner48b5c422017-06-27 02:02:04 +0200115 # bpo-30776: Try to ignore false positives:
116 #
117 # [3, 0, 0]
118 # [0, 1, 0]
119 # [8, -8, 1]
120 #
121 # Expected leaks:
122 #
123 # [5, 5, 6]
124 # [10, 1, 1]
125 return all(delta >= 1 for delta in deltas)
126
Victor Stinner48b5c422017-06-27 02:02:04 +0200127 def check_fd_deltas(deltas):
128 return any(deltas)
129
Victor Stinner3844fe52015-09-26 10:38:01 +0200130 failed = False
131 for deltas, item_name, checker in [
132 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200133 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +0200134 (fd_deltas, 'file descriptors', check_fd_deltas)
135 ]:
136 # ignore warmup runs
137 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200138 if checker(deltas):
139 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner5aaac942019-04-09 14:23:47 +0200140 test_name, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200141 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200142 with open(fname, "a") as refrep:
143 print(msg, file=refrep)
144 refrep.flush()
145 failed = True
146 return failed
147
148
149def dash_R_cleanup(fs, ps, pic, zdc, abcs):
Victor Stinner5aaac942019-04-09 14:23:47 +0200150 import copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200151 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200152
Victor Stinner3844fe52015-09-26 10:38:01 +0200153 # Restore some original values.
154 warnings.filters[:] = fs
155 copyreg.dispatch_table.clear()
156 copyreg.dispatch_table.update(ps)
157 sys.path_importer_cache.clear()
158 sys.path_importer_cache.update(pic)
159 try:
160 import zipimport
161 except ImportError:
162 pass # Run unmodified on platforms without zipimport support
163 else:
164 zipimport._zip_directory_cache.clear()
165 zipimport._zip_directory_cache.update(zdc)
166
167 # clear type cache
168 sys._clear_type_cache()
169
170 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100171 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
172 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100173 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200174 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000175 for ref in abcs.get(obj, set()):
176 if ref() is not None:
177 obj.register(ref())
178 obj._abc_caches_clear()
Victor Stinner3844fe52015-09-26 10:38:01 +0200179
Serhiy Storchaka83910262016-11-11 11:46:44 +0200180 clear_caches()
181
Serhiy Storchaka83910262016-11-11 11:46:44 +0200182
183def clear_caches():
Serhiy Storchaka83910262016-11-11 11:46:44 +0200184 # Clear the warnings registry, so they can be displayed again
185 for mod in sys.modules.values():
186 if hasattr(mod, '__warningregistry__'):
187 del mod.__warningregistry__
188
Victor Stinner3844fe52015-09-26 10:38:01 +0200189 # Flush standard output, so that buffered data is sent to the OS and
190 # associated Python objects are reclaimed.
191 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
192 if stream is not None:
193 stream.flush()
194
195 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200196 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200197 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200198 distutils_dir_util = sys.modules['distutils.dir_util']
199 except KeyError:
200 pass
201 else:
202 distutils_dir_util._path_created.clear()
203 re.purge()
204
205 try:
206 _strptime = sys.modules['_strptime']
207 except KeyError:
208 pass
209 else:
210 _strptime._regex_cache.clear()
211
212 try:
213 urllib_parse = sys.modules['urllib.parse']
214 except KeyError:
215 pass
216 else:
217 urllib_parse.clear_cache()
218
219 try:
220 urllib_request = sys.modules['urllib.request']
221 except KeyError:
222 pass
223 else:
224 urllib_request.urlcleanup()
225
226 try:
227 linecache = sys.modules['linecache']
228 except KeyError:
229 pass
230 else:
231 linecache.clearcache()
232
233 try:
234 mimetypes = sys.modules['mimetypes']
235 except KeyError:
236 pass
237 else:
238 mimetypes._default_mime_types()
239
240 try:
241 filecmp = sys.modules['filecmp']
242 except KeyError:
243 pass
244 else:
245 filecmp._cache.clear()
246
247 try:
248 struct = sys.modules['struct']
249 except KeyError:
250 pass
251 else:
252 struct._clearcache()
253
254 try:
255 doctest = sys.modules['doctest']
256 except KeyError:
257 pass
258 else:
259 doctest.master = None
260
261 try:
262 ctypes = sys.modules['ctypes']
263 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200264 pass
265 else:
266 ctypes._reset_cache()
267
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200268 try:
269 typing = sys.modules['typing']
270 except KeyError:
271 pass
272 else:
273 for f in typing._cleanups:
274 f()
275
Victor Stinner5aaac942019-04-09 14:23:47 +0200276 support.gc_collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200277
278
279def warm_caches():
280 # char cache
281 s = bytes(range(256))
282 for i in range(256):
283 s[i:i+1]
284 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200285 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200286 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200287 list(range(-5, 257))