blob: 6724488fcfb088e46c7755f81c793738e16eb186 [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:
11 def _get_dump(cls):
12 # For legacy Python version
13 return (cls._abc_registry, cls._abc_cache,
14 cls._abc_negative_cache, cls._abc_negative_cache_version)
Victor Stinner3844fe52015-09-26 10:38:01 +020015
16
17def dash_R(the_module, test, indirect_test, huntrleaks):
18 """Run a test multiple times, looking for reference leaks.
19
20 Returns:
21 False if the test didn't leak references; True if we detected refleaks.
22 """
23 # This code is hackish and inelegant, but it seems to do the job.
24 import copyreg
25 import collections.abc
26
27 if not hasattr(sys, 'gettotalrefcount'):
28 raise Exception("Tracking reference leaks requires a debug build "
29 "of Python")
30
31 # Save current values for dash_R_cleanup() to restore.
32 fs = warnings.filters[:]
33 ps = copyreg.dispatch_table.copy()
34 pic = sys.path_importer_cache.copy()
35 try:
36 import zipimport
37 except ImportError:
38 zdc = None # Run unmodified on platforms without zipimport support
39 else:
40 zdc = zipimport._zip_directory_cache.copy()
41 abcs = {}
42 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
43 if not isabstract(abc):
44 continue
45 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000046 abcs[obj] = _get_dump(obj)[0]
Victor Stinner3844fe52015-09-26 10:38:01 +020047
Victor Stinner6c2feab2017-09-01 13:05:27 +020048 # bpo-31217: Integer pool to get a single integer object for the same
49 # value. The pool is used to prevent false alarm when checking for memory
50 # block leaks. Fill the pool with values in -1000..1000 which are the most
51 # common (reference, memory block, file descriptor) differences.
52 int_pool = {value: value for value in range(-1000, 1000)}
53 def get_pooled_int(value):
54 return int_pool.setdefault(value, value)
55
Victor Stinner3844fe52015-09-26 10:38:01 +020056 nwarmup, ntracked, fname = huntrleaks
57 fname = os.path.join(support.SAVEDCWD, fname)
58 repcount = nwarmup + ntracked
59 rc_deltas = [0] * repcount
60 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020061 fd_deltas = [0] * repcount
Victor Stinner3844fe52015-09-26 10:38:01 +020062
63 print("beginning", repcount, "repetitions", file=sys.stderr)
Victor Stinnerf33536c2015-09-30 00:48:27 +020064 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
65 flush=True)
Victor Stinner9a142142015-09-30 13:51:17 +020066 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020067 rc_before = alloc_before = fd_before = 0
Victor Stinner3844fe52015-09-26 10:38:01 +020068 for i in range(repcount):
69 indirect_test()
Victor Stinner076fc872015-10-03 00:20:56 +020070 alloc_after, rc_after, fd_after = dash_R_cleanup(fs, ps, pic, zdc,
71 abcs)
Victor Stinner17a63e22017-02-08 13:06:08 +010072 print('.', end='', file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +020073 if i >= nwarmup:
Victor Stinner6c2feab2017-09-01 13:05:27 +020074 rc_deltas[i] = get_pooled_int(rc_after - rc_before)
75 alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
76 fd_deltas[i] = get_pooled_int(fd_after - fd_before)
Victor Stinner076fc872015-10-03 00:20:56 +020077 alloc_before = alloc_after
78 rc_before = rc_after
79 fd_before = fd_after
Victor Stinner3844fe52015-09-26 10:38:01 +020080 print(file=sys.stderr)
Victor Stinner48b5c422017-06-27 02:02:04 +020081
Victor Stinner3844fe52015-09-26 10:38:01 +020082 # These checkers return False on success, True on failure
83 def check_rc_deltas(deltas):
Victor Stinnerbeeca6e2017-06-29 10:32:49 +020084 # Checker for reference counters and memomry blocks.
85 #
Victor Stinner48b5c422017-06-27 02:02:04 +020086 # bpo-30776: Try to ignore false positives:
87 #
88 # [3, 0, 0]
89 # [0, 1, 0]
90 # [8, -8, 1]
91 #
92 # Expected leaks:
93 #
94 # [5, 5, 6]
95 # [10, 1, 1]
96 return all(delta >= 1 for delta in deltas)
97
Victor Stinner48b5c422017-06-27 02:02:04 +020098 def check_fd_deltas(deltas):
99 return any(deltas)
100
Victor Stinner3844fe52015-09-26 10:38:01 +0200101 failed = False
102 for deltas, item_name, checker in [
103 (rc_deltas, 'references', check_rc_deltas),
Victor Stinnerbeeca6e2017-06-29 10:32:49 +0200104 (alloc_deltas, 'memory blocks', check_rc_deltas),
Victor Stinner48b5c422017-06-27 02:02:04 +0200105 (fd_deltas, 'file descriptors', check_fd_deltas)
106 ]:
107 # ignore warmup runs
108 deltas = deltas[nwarmup:]
Victor Stinner3844fe52015-09-26 10:38:01 +0200109 if checker(deltas):
110 msg = '%s leaked %s %s, sum=%s' % (
Victor Stinner48b5c422017-06-27 02:02:04 +0200111 test, deltas, item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200112 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200113 with open(fname, "a") as refrep:
114 print(msg, file=refrep)
115 refrep.flush()
116 failed = True
117 return failed
118
119
120def dash_R_cleanup(fs, ps, pic, zdc, abcs):
121 import gc, copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200122 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200123
Victor Stinner3844fe52015-09-26 10:38:01 +0200124 # Restore some original values.
125 warnings.filters[:] = fs
126 copyreg.dispatch_table.clear()
127 copyreg.dispatch_table.update(ps)
128 sys.path_importer_cache.clear()
129 sys.path_importer_cache.update(pic)
130 try:
131 import zipimport
132 except ImportError:
133 pass # Run unmodified on platforms without zipimport support
134 else:
135 zipimport._zip_directory_cache.clear()
136 zipimport._zip_directory_cache.update(zdc)
137
138 # clear type cache
139 sys._clear_type_cache()
140
141 # Clear ABC registries, restoring previously saved ABC registries.
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100142 abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
143 abs_classes = filter(isabstract, abs_classes)
Ivan Levkivskyi7acffa22017-03-05 19:15:20 +0100144 for abc in abs_classes:
Victor Stinner3844fe52015-09-26 10:38:01 +0200145 for obj in abc.__subclasses__() + [abc]:
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000146 for ref in abcs.get(obj, set()):
147 if ref() is not None:
148 obj.register(ref())
149 obj._abc_caches_clear()
Victor Stinner3844fe52015-09-26 10:38:01 +0200150
Serhiy Storchaka83910262016-11-11 11:46:44 +0200151 clear_caches()
152
153 # Collect cyclic trash and read memory statistics immediately after.
154 func1 = sys.getallocatedblocks
155 func2 = sys.gettotalrefcount
156 gc.collect()
Antoine Pitrou896145d2017-07-22 13:22:54 +0200157 return func1(), func2(), support.fd_count()
Serhiy Storchaka83910262016-11-11 11:46:44 +0200158
159
160def clear_caches():
161 import gc
162
163 # Clear the warnings registry, so they can be displayed again
164 for mod in sys.modules.values():
165 if hasattr(mod, '__warningregistry__'):
166 del mod.__warningregistry__
167
Victor Stinner3844fe52015-09-26 10:38:01 +0200168 # Flush standard output, so that buffered data is sent to the OS and
169 # associated Python objects are reclaimed.
170 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
171 if stream is not None:
172 stream.flush()
173
174 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200175 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200176 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200177 distutils_dir_util = sys.modules['distutils.dir_util']
178 except KeyError:
179 pass
180 else:
181 distutils_dir_util._path_created.clear()
182 re.purge()
183
184 try:
185 _strptime = sys.modules['_strptime']
186 except KeyError:
187 pass
188 else:
189 _strptime._regex_cache.clear()
190
191 try:
192 urllib_parse = sys.modules['urllib.parse']
193 except KeyError:
194 pass
195 else:
196 urllib_parse.clear_cache()
197
198 try:
199 urllib_request = sys.modules['urllib.request']
200 except KeyError:
201 pass
202 else:
203 urllib_request.urlcleanup()
204
205 try:
206 linecache = sys.modules['linecache']
207 except KeyError:
208 pass
209 else:
210 linecache.clearcache()
211
212 try:
213 mimetypes = sys.modules['mimetypes']
214 except KeyError:
215 pass
216 else:
217 mimetypes._default_mime_types()
218
219 try:
220 filecmp = sys.modules['filecmp']
221 except KeyError:
222 pass
223 else:
224 filecmp._cache.clear()
225
226 try:
227 struct = sys.modules['struct']
228 except KeyError:
229 pass
230 else:
231 struct._clearcache()
232
233 try:
234 doctest = sys.modules['doctest']
235 except KeyError:
236 pass
237 else:
238 doctest.master = None
239
240 try:
241 ctypes = sys.modules['ctypes']
242 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200243 pass
244 else:
245 ctypes._reset_cache()
246
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200247 try:
248 typing = sys.modules['typing']
249 except KeyError:
250 pass
251 else:
252 for f in typing._cleanups:
253 f()
254
Victor Stinner3844fe52015-09-26 10:38:01 +0200255 gc.collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200256
257
258def warm_caches():
259 # char cache
260 s = bytes(range(256))
261 for i in range(256):
262 s[i:i+1]
263 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200264 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200265 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200266 list(range(-5, 257))