Mercurial > cpython-lru_cache-weakref
diff Modules/_ctypes/callbacks.c @ 46546:4ff8dfaec3fc legacy-trunk
Remove cyclic reference in CFuncPtr instances; see issue #2682.
Backport candidate for the release25-maint branch.
| author | Thomas Heller <theller@ctypes.org> |
|---|---|
| date | Thu, 24 Apr 2008 18:14:19 +0000 |
| parents | 1c9ac00c4758 |
| children | ad3417503636 |
line wrap: on
line diff
--- a/Modules/_ctypes/callbacks.c Thu Apr 24 18:07:05 2008 +0000 +++ b/Modules/_ctypes/callbacks.c Thu Apr 24 18:14:19 2008 +0000 @@ -12,6 +12,73 @@ #endif #include "ctypes.h" +/**************************************************************/ + +static CThunkObject_dealloc(PyObject *_self) +{ + CThunkObject *self = (CThunkObject *)_self; + Py_XDECREF(self->converters); + Py_XDECREF(self->callable); + Py_XDECREF(self->restype); + if (self->pcl) + FreeClosure(self->pcl); + PyObject_Del(self); +} + +static int +CThunkObject_traverse(PyObject *_self, visitproc visit, void *arg) +{ + CThunkObject *self = (CThunkObject *)_self; + Py_VISIT(self->converters); + Py_VISIT(self->callable); + Py_VISIT(self->restype); + return 0; +} + +static int +CThunkObject_clear(PyObject *_self) +{ + CThunkObject *self = (CThunkObject *)_self; + Py_CLEAR(self->converters); + Py_CLEAR(self->callable); + Py_CLEAR(self->restype); + return 0; +} + +PyTypeObject CThunk_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_ctypes.CThunkObject", + sizeof(CThunkObject), /* tp_basicsize */ + sizeof(ffi_type), /* tp_itemsize */ + CThunkObject_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "CThunkObject", /* tp_doc */ + CThunkObject_traverse, /* tp_traverse */ + CThunkObject_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ +}; + +/**************************************************************/ + static void PrintError(char *msg, ...) { @@ -247,32 +314,56 @@ void **args, void *userdata) { - ffi_info *p = userdata; + CThunkObject *p = (CThunkObject *)userdata; _CallPythonObject(resp, - p->restype, + p->ffi_restype, p->setfunc, p->callable, p->converters, args); } -ffi_info *AllocFunctionCallback(PyObject *callable, - PyObject *converters, - PyObject *restype, - int is_cdecl) +static CThunkObject* CThunkObject_new(Py_ssize_t nArgs) +{ + CThunkObject *p; + int i; + + p = PyObject_NewVar(CThunkObject, &CThunk_Type, nArgs); + if (p == NULL) { + PyErr_NoMemory(); + return NULL; + } + + p->pcl = NULL; + memset(&p->cif, 0, sizeof(p->cif)); + p->converters = NULL; + p->callable = NULL; + p->setfunc = NULL; + p->ffi_restype = NULL; + + for (i = 0; i < nArgs + 1; ++i) + p->atypes[i] = NULL; + return p; +} + +CThunkObject *AllocFunctionCallback(PyObject *callable, + PyObject *converters, + PyObject *restype, + int is_cdecl) { int result; - ffi_info *p; + CThunkObject *p; Py_ssize_t nArgs, i; ffi_abi cc; nArgs = PySequence_Size(converters); - p = (ffi_info *)PyMem_Malloc(sizeof(ffi_info) + sizeof(ffi_type) * (nArgs)); - if (p == NULL) { - PyErr_NoMemory(); + p = CThunkObject_new(nArgs); + if (p == NULL) return NULL; - } + + assert(CThunk_CheckExact(p)); + p->pcl = MallocClosure(); if (p->pcl == NULL) { PyErr_NoMemory(); @@ -288,9 +379,11 @@ } p->atypes[i] = NULL; + Py_INCREF(restype); + p->restype = restype; if (restype == Py_None) { p->setfunc = NULL; - p->restype = &ffi_type_void; + p->ffi_restype = &ffi_type_void; } else { StgDictObject *dict = PyType_stgdict(restype); if (dict == NULL || dict->setfunc == NULL) { @@ -299,7 +392,7 @@ goto error; } p->setfunc = dict->setfunc; - p->restype = &dict->ffi_type_pointer; + p->ffi_restype = &dict->ffi_type_pointer; } cc = FFI_DEFAULT_ABI; @@ -323,16 +416,14 @@ goto error; } + Py_INCREF(converters); p->converters = converters; + Py_INCREF(callable); p->callable = callable; return p; error: - if (p) { - if (p->pcl) - FreeClosure(p->pcl); - PyMem_Free(p); - } + Py_XDECREF(p); return NULL; }
