blob: 77298d318898dbd69b98f86be4a398b85fa6ad06 [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
Hai Shifcce8c62020-08-08 05:55:35 +08007from test.support import os_helper
8
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +00009try:
10 from _abc import _get_dump
11except ImportError:
Victor Stinner79b5d292019-04-09 01:36:34 +020012 import weakref
13
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000014 def _get_dump(cls):
Victor Stinner79b5d292019-04-09 01:36:34 +020015 # Reimplement _get_dump() for pure-Python implementation of
16 # the abc module (Lib/_py_abc.py)
17 registry_weakrefs = set(weakref.ref(obj) for obj in cls._abc_registry)
18 return (registry_weakrefs, cls._abc_cache,
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000019 cls._abc_negative_cache, cls._abc_negative_cache_version)
Victor Stinner3844fe52015-09-26 10:38:01 +020020
21
Victor Stinner4d299832019-04-26 04:08:53 +020022def dash_R(ns, test_name, test_func):
Victor Stinner3844fe52015-09-26 10:38:01 +020023 """Run a test multiple times, looking for reference leaks.
24
25 Returns:
26 False if the test didn't leak references; True if we detected refleaks.
27 """
28 # This code is hackish and inelegant, but it seems to do the job.
29 import copyreg
30 import collections.abc
31
32 if not hasattr(sys, 'gettotalrefcount'):
33 raise Exception("Tracking reference leaks requires a debug build "
34 "of Python")
35
Victor Stinner5aaac942019-04-09 14:23:47 +020036 # Avoid false positives due to various caches
37 # filling slowly with random data:
38 warm_caches()
39
Victor Stinner3844fe52015-09-26 10:38:01 +020040 # Save current values for dash_R_cleanup() to restore.
41 fs = warnings.filters[:]
42 ps = copyreg.dispatch_table.copy()
43 pic = sys.path_importer_cache.copy()
44 try:
45 import zipimport
46 except ImportError:
47 zdc = None # Run unmodified on platforms without zipimport support
48 else:
49 zdc = zipimport._zip_directory_cache.copy()
50 abcs = {}
51 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
52 if not isabstract(abc):
53 continue
54 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000055 abcs[obj] = _get_dump(obj)[0]
Victor Stinner3844fe52015-09-26 10:38:01 +020056
Victor Stinner6c2feab2017-09-01 13:05:27 +020057 # bpo-31217: Integer pool to get a single integer object for the same
58 # value. The pool is used to prevent false alarm when checking for memory
59 # block leaks. Fill the pool with values in -1000..1000 which are the most
60 # common (reference, memory block, file descriptor) differences.
61 int_pool = {value: value for value in range(-1000, 1000)}
62 def get_pooled_int(value):
63 return int_pool.setdefault(value, value)
64
Victor Stinner5aaac942019-04-09 14:23:47 +020065 nwarmup, ntracked, fname = ns.huntrleaks
Hai Shifcce8c62020-08-08 05:55:35 +080066 fname = os.path.join(os_helper.SAVEDCWD, fname)
Victor Stinner3844fe52015-09-26 10:38:01 +020067 repcount = nwarmup + ntracked
Victor Stinner5aaac942019-04-09 14:23:47 +020068
69 # Pre-allocate to ensure that the loop doesn't allocate anything new
70 rep_range = list(range(repcount))
Victor Stinner3844fe52015-09-26 10:38:01 +020071 rc_deltas = [0] * repcount
72 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020073 fd_deltas = [0] * repcount
Victor Stinner5aaac942019-04-09 14:23:47 +020074 getallocatedblocks = sys.getallocatedblocks
75 gettotalrefcount = sys.gettotalrefcount
Hai Shifcce8c62020-08-08 05:55:35 +080076 fd_count = os_helper.fd_count
Victor Stinner3844fe52015-09-26 10:38:01 +020077
Victor Stinner9a142142015-09-30 13:51:17 +020078 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020079 rc_before = alloc_before = fd_before = 0
Victor Stinner5aaac942019-04-09 14:23:47 +020080
81 if not ns.quiet:
82 print("beginning", repcount, "repetitions", file=sys.stderr)
83 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
84 flush=True)
85
Victor Stinnerbb444782019-04-09 18:26:16 +020086 dash_R_cleanup(fs, ps, pic, zdc, abcs)
87
Victor Stinner5aaac942019-04-09 14:23:47 +020088 for i in rep_range:
89 test_func()
90 dash_R_cleanup(fs, ps, pic, zdc, abcs)
91
Victor Stinnerbb444782019-04-09 18:26:16 +020092 # dash_R_cleanup() ends with collecting cyclic trash:
93 # read memory statistics immediately after.
Victor Stinner5aaac942019-04-09 14:23:47 +020094 alloc_after = getallocatedblocks()
95 rc_after = gettotalrefcount()
96 fd_after = fd_count()
97
98 if not ns.quiet:
99 print('.', end='', file=sys.stderr, flush=True)
100
101 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
102 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
103 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
104
Victor Stinner076fc872015-10-03 00:20:56 +0200105 alloc_before = alloc_after
106 rc_before = rc_after
107 fd_before = fd_after
Victor Stinner5aaac942019-04-09 14:23:47 +0200108
109 if not ns.quiet:
110 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +0200111
Victor Stinner3844fe52015-09-26 10:38:01 +0200112 # These checkers return False on success, True on failure
113 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200114 # Checker for reference counters and memomry blocks.
115 #
Victor Stinner48b5c422017-06-27 02:02:04 +0200116 # bpo-30776: Try to ignore false positives:
117 #
118 # [3, 0, 0]
119 # [0, 1, 0]
120 # [8, -8, 1]
121 #
122 # Expected leaks:
123 #
124 # [5, 5, 6]
125 # [10, 1, 1]
126 return all(delta >= 1 for delta in deltas)
127
Victor Stinner48b5c422017-06-27 02:02:04 +0200128 def check_fd_deltas(deltas):
129 return any(deltas)
130
Victor Stinner3844fe52015-09-26 10:38:01 +0200131 failed = False
132 for deltas, item_name, checker in [
133 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200134 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +0200135 (fd_deltas, 'file descriptors', check_fd_deltas)
136 ]:
137 # ignore warmup runs
138 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200139 if checker(deltas):
140 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner5aaac942019-04-09 14:23:47 +0200141 test_name, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200142 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200143 with open(fname, "a") as refrep:
144 print(msg, file=refrep)
145 refrep.flush()
146 failed = True
147 return failed
148
149
150def dash_R_cleanup(fs, ps, pic, zdc, abcs):
Victor Stinner5aaac942019-04-09 14:23:47 +0200151 import copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200152 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200153
Victor Stinner3844fe52015-09-26 10:38:01 +0200154 # Restore some original values.
155 warnings.filters[:] = fs
156 copyreg.dispatch_table.clear()
157 copyreg.dispatch_table.update(ps)
158 sys.path_importer_cache.clear()
159 sys.path_importer_cache.update(pic)
160 try:
161 import zipimport
162 except ImportError:
163 pass # Run unmodified on platforms without zipimport support
164 else:
165 zipimport._zip_directory_cache.clear()
166 zipimport._zip_directory_cache.update(zdc)
167
168 # clear type cache
169 sys._clear_type_cache()
170
171 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100172 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
173 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100174 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200175 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000176 for ref in abcs.get(obj, set()):
177 if ref() is not None:
178 obj.register(ref())
179 obj._abc_caches_clear()
Victor Stinner3844fe52015-09-26 10:38:01 +0200180
Serhiy Storchaka83910262016-11-11 11:46:44 +0200181 clear_caches()
182
Serhiy Storchaka83910262016-11-11 11:46:44 +0200183
184def clear_caches():
Serhiy Storchaka83910262016-11-11 11:46:44 +0200185 # Clear the warnings registry, so they can be displayed again
186 for mod in sys.modules.values():
187 if hasattr(mod, '__warningregistry__'):
188 del mod.__warningregistry__
189
Victor Stinner3844fe52015-09-26 10:38:01 +0200190 # Flush standard output, so that buffered data is sent to the OS and
191 # associated Python objects are reclaimed.
192 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
193 if stream is not None:
194 stream.flush()
195
196 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200197 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200198 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200199 distutils_dir_util = sys.modules['distutils.dir_util']
200 except KeyError:
201 pass
202 else:
203 distutils_dir_util._path_created.clear()
204 re.purge()
205
206 try:
207 _strptime = sys.modules['_strptime']
208 except KeyError:
209 pass
210 else:
211 _strptime._regex_cache.clear()
212
213 try:
214 urllib_parse = sys.modules['urllib.parse']
215 except KeyError:
216 pass
217 else:
218 urllib_parse.clear_cache()
219
220 try:
221 urllib_request = sys.modules['urllib.request']
222 except KeyError:
223 pass
224 else:
225 urllib_request.urlcleanup()
226
227 try:
228 linecache = sys.modules['linecache']
229 except KeyError:
230 pass
231 else:
232 linecache.clearcache()
233
234 try:
235 mimetypes = sys.modules['mimetypes']
236 except KeyError:
237 pass
238 else:
239 mimetypes._default_mime_types()
240
241 try:
242 filecmp = sys.modules['filecmp']
243 except KeyError:
244 pass
245 else:
246 filecmp._cache.clear()
247
248 try:
249 struct = sys.modules['struct']
250 except KeyError:
251 pass
252 else:
253 struct._clearcache()
254
255 try:
256 doctest = sys.modules['doctest']
257 except KeyError:
258 pass
259 else:
260 doctest.master = None
261
262 try:
263 ctypes = sys.modules['ctypes']
264 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200265 pass
266 else:
267 ctypes._reset_cache()
268
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200269 try:
270 typing = sys.modules['typing']
271 except KeyError:
272 pass
273 else:
274 for f in typing._cleanups:
275 f()
276
Victor Stinner5aaac942019-04-09 14:23:47 +0200277 support.gc_collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200278
279
280def warm_caches():
281 # char cache
282 s = bytes(range(256))
283 for i in range(256):
284 s[i:i+1]
285 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200286 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200287 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200288 list(range(-5, 257))