mirror of https://github.com/python/cpython
ctypes CThunkObject was not registered correctly with the cycle
garbage collector, leading to possible leaks when using callback functions.
This commit is contained in:
parent
429a74a11a
commit
92bd059c67
|
@ -118,6 +118,22 @@ class Callbacks(unittest.TestCase):
|
||||||
prototype = self.functype.im_func(object)
|
prototype = self.functype.im_func(object)
|
||||||
self.assertRaises(TypeError, prototype, lambda: None)
|
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:
|
try:
|
||||||
WINFUNCTYPE
|
WINFUNCTYPE
|
||||||
except NameError:
|
except NameError:
|
||||||
|
|
|
@ -27,6 +27,9 @@ Core and Builtins
|
||||||
Library
|
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
|
- Issue #7970: email.Generator.flatten now correctly flattens message/rfc822
|
||||||
messages parsed by email.Parser.HeaderParser.
|
messages parsed by email.Parser.HeaderParser.
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ CThunkObject_dealloc(PyObject *_self)
|
||||||
Py_XDECREF(self->restype);
|
Py_XDECREF(self->restype);
|
||||||
if (self->pcl)
|
if (self->pcl)
|
||||||
_ctypes_free_closure(self->pcl);
|
_ctypes_free_closure(self->pcl);
|
||||||
PyObject_Del(self);
|
PyObject_GC_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -66,7 +66,7 @@ PyTypeObject PyCThunk_Type = {
|
||||||
0, /* tp_getattro */
|
0, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
||||||
"CThunkObject", /* tp_doc */
|
"CThunkObject", /* tp_doc */
|
||||||
CThunkObject_traverse, /* tp_traverse */
|
CThunkObject_traverse, /* tp_traverse */
|
||||||
CThunkObject_clear, /* tp_clear */
|
CThunkObject_clear, /* tp_clear */
|
||||||
|
@ -385,7 +385,7 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
|
||||||
CThunkObject *p;
|
CThunkObject *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p = PyObject_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
|
p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -400,6 +400,7 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
|
||||||
|
|
||||||
for (i = 0; i < nArgs + 1; ++i)
|
for (i = 0; i < nArgs + 1; ++i)
|
||||||
p->atypes[i] = NULL;
|
p->atypes[i] = NULL;
|
||||||
|
PyObject_GC_Track((PyObject *)p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue