summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2010-02-23 20:11:44 (GMT)
committerThomas Heller <theller@ctypes.org>2010-02-23 20:11:44 (GMT)
commit92bd059c678e85df3c6fff24dbf4b8b7b27b61bd (patch)
tree81a7cefecb6e82795b2c67b958d1a177dcd20549
parent429a74a11a0b31c6a7093a89f595f834daaa1b79 (diff)
downloadcpython-92bd059c678e85df3c6fff24dbf4b8b7b27b61bd.zip
cpython-92bd059c678e85df3c6fff24dbf4b8b7b27b61bd.tar.gz
cpython-92bd059c678e85df3c6fff24dbf4b8b7b27b61bd.tar.bz2
ctypes CThunkObject was not registered correctly with the cycle
garbage collector, leading to possible leaks when using callback functions.
-rw-r--r--Lib/ctypes/test/test_callbacks.py16
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_ctypes/callbacks.c7
3 files changed, 23 insertions, 3 deletions
diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py
index b9e6628..6f517b1 100644
--- a/Lib/ctypes/test/test_callbacks.py
+++ b/Lib/ctypes/test/test_callbacks.py
@@ -118,6 +118,22 @@ class Callbacks(unittest.TestCase):
prototype = self.functype.im_func(object)
self.assertRaises(TypeError, prototype, lambda: None)
+ def test_issue_7959(self):
+ proto = self.functype.im_func(None)
+
+ class X(object):
+ def func(self): pass
+ def __init__(self):
+ self.v = proto(self.func)
+
+ import gc
+ for i in range(32):
+ X()
+ gc.collect()
+ live = [x for x in gc.get_objects()
+ if isinstance(x, X)]
+ self.failUnlessEqual(len(live), 0)
+
try:
WINFUNCTYPE
except NameError:
diff --git a/Misc/NEWS b/Misc/NEWS
index 1345a56..ff04b28 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
Library
-------
+- Issue #7959: ctypes callback functions are now registered correctly
+ with the cylce garbage collector.
+
- Issue #7970: email.Generator.flatten now correctly flattens message/rfc822
messages parsed by email.Parser.HeaderParser.
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index a643970..afdd947 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -23,7 +23,7 @@ CThunkObject_dealloc(PyObject *_self)
Py_XDECREF(self->restype);
if (self->pcl)
_ctypes_free_closure(self->pcl);
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static int
@@ -66,7 +66,7 @@ PyTypeObject PyCThunk_Type = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
"CThunkObject", /* tp_doc */
CThunkObject_traverse, /* tp_traverse */
CThunkObject_clear, /* tp_clear */
@@ -385,7 +385,7 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
CThunkObject *p;
int i;
- p = PyObject_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
+ p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
if (p == NULL) {
PyErr_NoMemory();
return NULL;
@@ -400,6 +400,7 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
for (i = 0; i < nArgs + 1; ++i)
p->atypes[i] = NULL;
+ PyObject_GC_Track((PyObject *)p);
return p;
}