blob: d9f72208cfda0e2de85c6d64e9aa410c4e92fe09 [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
8
9
Victor Stinner076fc872015-10-03 00:20:56 +020010try:
11 MAXFD = os.sysconf("SC_OPEN_MAX")
12except Exception:
13 MAXFD = 256
14
15
16def fd_count():
17 """Count the number of open file descriptors"""
18 if sys.platform.startswith(('linux', 'freebsd')):
19 try:
20 names = os.listdir("/proc/self/fd")
21 return len(names)
22 except FileNotFoundError:
23 pass
24
25 count = 0
26 for fd in range(MAXFD):
27 try:
28 # Prefer dup() over fstat(). fstat() can require input/output
29 # whereas dup() doesn't.
30 fd2 = os.dup(fd)
31 except OSError as e:
32 if e.errno != errno.EBADF:
33 raise
34 else:
35 os.close(fd2)
36 count += 1
37 return count
38
39
Victor Stinner3844fe52015-09-26 10:38:01 +020040def dash_R(the_module, test, indirect_test, huntrleaks):
41 """Run a test multiple times, looking for reference leaks.
42
43 Returns:
44 False if the test didn't leak references; True if we detected refleaks.
45 """
46 # This code is hackish and inelegant, but it seems to do the job.
47 import copyreg
48 import collections.abc
49
50 if not hasattr(sys, 'gettotalrefcount'):
51 raise Exception("Tracking reference leaks requires a debug build "
52 "of Python")
53
54 # Save current values for dash_R_cleanup() to restore.
55 fs = warnings.filters[:]
56 ps = copyreg.dispatch_table.copy()
57 pic = sys.path_importer_cache.copy()
58 try:
59 import zipimport
60 except ImportError:
61 zdc = None # Run unmodified on platforms without zipimport support
62 else:
63 zdc = zipimport._zip_directory_cache.copy()
64 abcs = {}
65 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
66 if not isabstract(abc):
67 continue
68 for obj in abc.__subclasses__() + [abc]:
69 abcs[obj] = obj._abc_registry.copy()
70
71 nwarmup, ntracked, fname = huntrleaks
72 fname = os.path.join(support.SAVEDCWD, fname)
73 repcount = nwarmup + ntracked
74 rc_deltas = [0] * repcount
75 alloc_deltas = [0] * repcount
Victor Stinner076fc872015-10-03 00:20:56 +020076 fd_deltas = [0] * repcount
Victor Stinner3844fe52015-09-26 10:38:01 +020077
78 print("beginning", repcount, "repetitions", file=sys.stderr)
Victor Stinnerf33536c2015-09-30 00:48:27 +020079 print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
80 flush=True)
Victor Stinner9a142142015-09-30 13:51:17 +020081 # initialize variables to make pyflakes quiet
Victor Stinner076fc872015-10-03 00:20:56 +020082 rc_before = alloc_before = fd_before = 0
Victor Stinner3844fe52015-09-26 10:38:01 +020083 for i in range(repcount):
84 indirect_test()
Victor Stinner076fc872015-10-03 00:20:56 +020085 alloc_after, rc_after, fd_after = dash_R_cleanup(fs, ps, pic, zdc,
86 abcs)
Victor Stinner17a63e22017-02-08 13:06:08 +010087 print('.', end='', file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +020088 if i >= nwarmup:
89 rc_deltas[i] = rc_after - rc_before
90 alloc_deltas[i] = alloc_after - alloc_before
Victor Stinner076fc872015-10-03 00:20:56 +020091 fd_deltas[i] = fd_after - fd_before
92 alloc_before = alloc_after
93 rc_before = rc_after
94 fd_before = fd_after
Victor Stinner3844fe52015-09-26 10:38:01 +020095 print(file=sys.stderr)
96 # These checkers return False on success, True on failure
97 def check_rc_deltas(deltas):
98 return any(deltas)
99 def check_alloc_deltas(deltas):
100 # At least 1/3rd of 0s
101 if 3 * deltas.count(0) < len(deltas):
102 return True
103 # Nothing else than 1s, 0s and -1s
104 if not set(deltas) <= {1,0,-1}:
105 return True
106 return False
107 failed = False
108 for deltas, item_name, checker in [
109 (rc_deltas, 'references', check_rc_deltas),
Victor Stinner076fc872015-10-03 00:20:56 +0200110 (alloc_deltas, 'memory blocks', check_alloc_deltas),
111 (fd_deltas, 'file descriptors', check_rc_deltas)]:
Victor Stinner3844fe52015-09-26 10:38:01 +0200112 if checker(deltas):
113 msg = '%s leaked %s %s, sum=%s' % (
114 test, deltas[nwarmup:], item_name, sum(deltas))
Victor Stinnerf33536c2015-09-30 00:48:27 +0200115 print(msg, file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200116 with open(fname, "a") as refrep:
117 print(msg, file=refrep)
118 refrep.flush()
119 failed = True
120 return failed
121
122
123def dash_R_cleanup(fs, ps, pic, zdc, abcs):
124 import gc, copyreg
Serhiy Storchaka83910262016-11-11 11:46:44 +0200125 import collections.abc
Victor Stinner3844fe52015-09-26 10:38:01 +0200126 from weakref import WeakSet
127
Victor Stinner3844fe52015-09-26 10:38:01 +0200128 # Restore some original values.
129 warnings.filters[:] = fs
130 copyreg.dispatch_table.clear()
131 copyreg.dispatch_table.update(ps)
132 sys.path_importer_cache.clear()
133 sys.path_importer_cache.update(pic)
134 try:
135 import zipimport
136 except ImportError:
137 pass # Run unmodified on platforms without zipimport support
138 else:
139 zipimport._zip_directory_cache.clear()
140 zipimport._zip_directory_cache.update(zdc)
141
142 # clear type cache
143 sys._clear_type_cache()
144
145 # Clear ABC registries, restoring previously saved ABC registries.
146 for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
147 if not isabstract(abc):
148 continue
149 for obj in abc.__subclasses__() + [abc]:
150 obj._abc_registry = abcs.get(obj, WeakSet()).copy()
151 obj._abc_cache.clear()
152 obj._abc_negative_cache.clear()
153
Serhiy Storchaka83910262016-11-11 11:46:44 +0200154 clear_caches()
155
156 # Collect cyclic trash and read memory statistics immediately after.
157 func1 = sys.getallocatedblocks
158 func2 = sys.gettotalrefcount
159 gc.collect()
160 return func1(), func2(), fd_count()
161
162
163def clear_caches():
164 import gc
165
166 # Clear the warnings registry, so they can be displayed again
167 for mod in sys.modules.values():
168 if hasattr(mod, '__warningregistry__'):
169 del mod.__warningregistry__
170
Victor Stinner3844fe52015-09-26 10:38:01 +0200171 # Flush standard output, so that buffered data is sent to the OS and
172 # associated Python objects are reclaimed.
173 for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__):
174 if stream is not None:
175 stream.flush()
176
177 # Clear assorted module caches.
Serhiy Storchaka83910262016-11-11 11:46:44 +0200178 # Don't worry about resetting the cache if the module is not loaded
Victor Stinner3844fe52015-09-26 10:38:01 +0200179 try:
Serhiy Storchaka83910262016-11-11 11:46:44 +0200180 distutils_dir_util = sys.modules['distutils.dir_util']
181 except KeyError:
182 pass
183 else:
184 distutils_dir_util._path_created.clear()
185 re.purge()
186
187 try:
188 _strptime = sys.modules['_strptime']
189 except KeyError:
190 pass
191 else:
192 _strptime._regex_cache.clear()
193
194 try:
195 urllib_parse = sys.modules['urllib.parse']
196 except KeyError:
197 pass
198 else:
199 urllib_parse.clear_cache()
200
201 try:
202 urllib_request = sys.modules['urllib.request']
203 except KeyError:
204 pass
205 else:
206 urllib_request.urlcleanup()
207
208 try:
209 linecache = sys.modules['linecache']
210 except KeyError:
211 pass
212 else:
213 linecache.clearcache()
214
215 try:
216 mimetypes = sys.modules['mimetypes']
217 except KeyError:
218 pass
219 else:
220 mimetypes._default_mime_types()
221
222 try:
223 filecmp = sys.modules['filecmp']
224 except KeyError:
225 pass
226 else:
227 filecmp._cache.clear()
228
229 try:
230 struct = sys.modules['struct']
231 except KeyError:
232 pass
233 else:
234 struct._clearcache()
235
236 try:
237 doctest = sys.modules['doctest']
238 except KeyError:
239 pass
240 else:
241 doctest.master = None
242
243 try:
244 ctypes = sys.modules['ctypes']
245 except KeyError:
Victor Stinner3844fe52015-09-26 10:38:01 +0200246 pass
247 else:
248 ctypes._reset_cache()
249
Serhiy Storchaka04c954d2016-11-09 23:51:54 +0200250 try:
251 typing = sys.modules['typing']
252 except KeyError:
253 pass
254 else:
255 for f in typing._cleanups:
256 f()
257
Victor Stinner3844fe52015-09-26 10:38:01 +0200258 gc.collect()
Victor Stinner3844fe52015-09-26 10:38:01 +0200259
260
261def warm_caches():
262 # char cache
263 s = bytes(range(256))
264 for i in range(256):
265 s[i:i+1]
266 # unicode cache
Victor Stinner9a142142015-09-30 13:51:17 +0200267 [chr(i) for i in range(256)]
Victor Stinner3844fe52015-09-26 10:38:01 +0200268 # int cache
Victor Stinner9a142142015-09-30 13:51:17 +0200269 list(range(-5, 257))