summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJulian Taylor <jtaylor.debian@googlemail.com>2014-07-05 23:09:12 +0200
committerJulian Taylor <jtaylor.debian@googlemail.com>2014-07-05 23:13:30 +0200
commitc9c53ea985565d7d78f23519b9c5db630ac76d3d (patch)
treecd87185bf17c08fcae036c1a42ffda56be1842ff /tools
parent7a2b14ae0adb762a3eb8991595b14f74f004f435 (diff)
downloadnumpy-c9c53ea985565d7d78f23519b9c5db630ac76d3d.tar.gz
BUG: disable garbage collector during memory allocation hook
When a cython object contains numpy arrays the pure python allocation hook can trigger during cythons __dealloc__ method and trigger a second deletion of the object currently being deleted. To minimize the probabily that that happens disable the garbage collector during the hook. As this involves python calls it is still possible that a double delete occurs but chances are lowered, a proper solution would be C only hook like python 3.4 tracemalloc module. Closes gh-4834
Diffstat (limited to 'tools')
-rw-r--r--tools/allocation_tracking/track_allocations.py10
1 files changed, 10 insertions, 0 deletions
diff --git a/tools/allocation_tracking/track_allocations.py b/tools/allocation_tracking/track_allocations.py
index 2006217c2..dfc354eb5 100644
--- a/tools/allocation_tracking/track_allocations.py
+++ b/tools/allocation_tracking/track_allocations.py
@@ -1,6 +1,7 @@
from __future__ import division, absolute_import, print_function
import numpy as np
+import gc
import inspect
from alloc_hook import NumpyAllocHook
@@ -35,12 +36,21 @@ class AllocationTracker(object):
self.numpy_hook.__exit__()
def hook(self, inptr, outptr, size):
+ # minimize the chances that the garbage collector kicks in during a
+ # cython __dealloc__ call and causes a double delete of the current
+ # object. To avoid this fully the hook would have to avoid all python
+ # api calls, e.g. by being implemented in C like python 3.4's
+ # tracemalloc module
+ gc_on = gc.isenabled()
+ gc.disable()
if outptr == 0: # it's a free
self.free_cb(inptr)
elif inptr != 0: # realloc
self.realloc_cb(inptr, outptr, size)
else: # malloc
self.alloc_cb(outptr, size)
+ if gc_on:
+ gc.enable()
def alloc_cb(self, ptr, size):
if size >= self.threshold: