From: Thomas Heller Date: Tue, 23 Feb 2010 20:11:44 +0000 (+0000) Subject: ctypes CThunkObject was not registered correctly with the cycle X-Git-Tag: v2.7a4~128 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=92bd059c678e85df3c6fff24dbf4b8b7b27b61bd;p=python ctypes CThunkObject was not registered correctly with the cycle garbage collector, leading to possible leaks when using callback functions. --- diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py index b9e662804b..6f517b1c11 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 1345a56b6e..ff04b289d9 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 a643970586..afdd9472f4 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; }