forked from ethanchewy/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathleakfinder.py
More file actions
73 lines (67 loc) · 2.13 KB
/
leakfinder.py
File metadata and controls
73 lines (67 loc) · 2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import sys, gc
import cStringIO
import traceback
# Track allocations to detect memory leaks.
# So far, this is used for lltype.malloc(flavor='raw').
TRACK_ALLOCATIONS = False
ALLOCATED = {}
class MallocMismatch(Exception):
def __str__(self):
dict = self.args[0]
dict2 = {}
for obj, traceback in dict.items():
traceback = traceback.splitlines()
if len(traceback) > 8:
traceback = [' ...'] + traceback[-6:]
traceback = '\n'.join(traceback)
dict2.setdefault(traceback, [])
dict2[traceback].append(obj)
lines = ['{']
for traceback, objs in dict2.items():
lines.append('')
for obj in objs:
lines.append('%s:' % (obj,))
lines.append(traceback)
lines.append('}')
return '\n'.join(lines)
def start_tracking_allocations():
global TRACK_ALLOCATIONS
if TRACK_ALLOCATIONS:
result = ALLOCATED.copy() # nested start
else:
result = None
TRACK_ALLOCATIONS = True
ALLOCATED.clear()
return result
def stop_tracking_allocations(check, prev=None, do_collection=gc.collect):
global TRACK_ALLOCATIONS
assert TRACK_ALLOCATIONS
for i in range(5):
if not ALLOCATED:
break
do_collection()
result = ALLOCATED.copy()
ALLOCATED.clear()
if prev is None:
TRACK_ALLOCATIONS = False
else:
ALLOCATED.update(prev)
if check and result:
raise MallocMismatch(result)
return result
def remember_malloc(obj, framedepth=1):
if TRACK_ALLOCATIONS:
frame = sys._getframe(framedepth)
sio = cStringIO.StringIO()
traceback.print_stack(frame, limit=10, file=sio)
tb = sio.getvalue()
ALLOCATED[obj] = tb
def remember_free(obj):
if TRACK_ALLOCATIONS:
if obj not in ALLOCATED:
# rehashing is needed because some objects' hash may change
# e.g. when lltype objects are turned into <C object>
items = ALLOCATED.items()
ALLOCATED.clear()
ALLOCATED.update(items)
del ALLOCATED[obj]