mirror of https://github.com/python/cpython
bpo-42972: Fully support GC for pyexpat, unicodedata, and dbm/gdbm heap types (GH-26376)
* bpo-42972: pyexpat * bpo-42972: unicodedata * bpo-42972: dbm/gdbm
This commit is contained in:
parent
fbff5387c3
commit
59af59c2df
|
@ -65,13 +65,14 @@ typedef struct {
|
|||
static PyObject *
|
||||
newdbmobject(_dbm_state *state, const char *file, int flags, int mode)
|
||||
{
|
||||
dbmobject *dp;
|
||||
|
||||
dp = PyObject_New(dbmobject, state->dbm_type);
|
||||
if (dp == NULL)
|
||||
dbmobject *dp = PyObject_GC_New(dbmobject, state->dbm_type);
|
||||
if (dp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
dp->di_size = -1;
|
||||
dp->flags = flags;
|
||||
PyObject_GC_Track(dp);
|
||||
|
||||
/* See issue #19296 */
|
||||
if ( (dp->di_dbm = dbm_open((char *)file, flags, mode)) == 0 ) {
|
||||
PyErr_SetFromErrnoWithFilename(state->dbm_error, file);
|
||||
|
@ -82,10 +83,17 @@ newdbmobject(_dbm_state *state, const char *file, int flags, int mode)
|
|||
}
|
||||
|
||||
/* Methods */
|
||||
static int
|
||||
dbm_traverse(dbmobject *dp, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(Py_TYPE(dp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dbm_dealloc(dbmobject *dp)
|
||||
{
|
||||
PyObject_GC_UnTrack(dp);
|
||||
if (dp->di_dbm) {
|
||||
dbm_close(dp->di_dbm);
|
||||
}
|
||||
|
@ -397,6 +405,7 @@ static PyMethodDef dbm_methods[] = {
|
|||
|
||||
static PyType_Slot dbmtype_spec_slots[] = {
|
||||
{Py_tp_dealloc, dbm_dealloc},
|
||||
{Py_tp_traverse, dbm_traverse},
|
||||
{Py_tp_methods, dbm_methods},
|
||||
{Py_sq_contains, dbm_contains},
|
||||
{Py_mp_length, dbm_length},
|
||||
|
@ -413,7 +422,8 @@ static PyType_Spec dbmtype_spec = {
|
|||
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
|
||||
// which prevents to create a subclass.
|
||||
// So calling PyType_GetModuleState() in this file is always safe.
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
|
||||
Py_TPFLAGS_HAVE_GC),
|
||||
.slots = dbmtype_spec_slots,
|
||||
};
|
||||
|
||||
|
|
|
@ -74,12 +74,14 @@ nextkey, reorganize, and sync.");
|
|||
static PyObject *
|
||||
newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
|
||||
{
|
||||
gdbmobject *dp = PyObject_New(gdbmobject, state->gdbm_type);
|
||||
gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type);
|
||||
if (dp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
dp->di_size = -1;
|
||||
errno = 0;
|
||||
PyObject_GC_Track(dp);
|
||||
|
||||
if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
|
||||
if (errno != 0) {
|
||||
PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
|
||||
|
@ -94,10 +96,17 @@ newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
|
|||
}
|
||||
|
||||
/* Methods */
|
||||
static int
|
||||
gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(Py_TYPE(dp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gdbm_dealloc(gdbmobject *dp)
|
||||
{
|
||||
PyObject_GC_UnTrack(dp);
|
||||
if (dp->di_dbm) {
|
||||
gdbm_close(dp->di_dbm);
|
||||
}
|
||||
|
@ -554,6 +563,7 @@ static PyMethodDef gdbm_methods[] = {
|
|||
|
||||
static PyType_Slot gdbmtype_spec_slots[] = {
|
||||
{Py_tp_dealloc, gdbm_dealloc},
|
||||
{Py_tp_traverse, gdbm_traverse},
|
||||
{Py_tp_methods, gdbm_methods},
|
||||
{Py_sq_contains, gdbm_contains},
|
||||
{Py_mp_length, gdbm_length},
|
||||
|
@ -570,7 +580,8 @@ static PyType_Spec gdbmtype_spec = {
|
|||
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
|
||||
// which prevents to create a subclass.
|
||||
// So calling PyType_GetModuleState() in this file is always safe.
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
|
||||
Py_TPFLAGS_HAVE_GC),
|
||||
.slots = gdbmtype_spec_slots,
|
||||
};
|
||||
|
||||
|
|
|
@ -731,6 +731,13 @@ profiler_clear(ProfilerObject *pObj, PyObject* noarg)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
profiler_traverse(ProfilerObject *op, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(Py_TYPE(op));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
profiler_dealloc(ProfilerObject *op)
|
||||
{
|
||||
|
@ -798,16 +805,14 @@ static PyType_Slot _lsprof_profiler_type_spec_slots[] = {
|
|||
{Py_tp_methods, profiler_methods},
|
||||
{Py_tp_dealloc, profiler_dealloc},
|
||||
{Py_tp_init, profiler_init},
|
||||
{Py_tp_alloc, PyType_GenericAlloc},
|
||||
{Py_tp_new, PyType_GenericNew},
|
||||
{Py_tp_free, PyObject_Del},
|
||||
{Py_tp_traverse, profiler_traverse},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static PyType_Spec _lsprof_profiler_type_spec = {
|
||||
.name = "_lsprof.Profiler",
|
||||
.basicsize = sizeof(ProfilerObject),
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
|
||||
.slots = _lsprof_profiler_type_spec_slots,
|
||||
};
|
||||
|
||||
|
|
|
@ -1182,19 +1182,34 @@ newxmlparseobject(pyexpat_state *state, const char *encoding,
|
|||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
static int
|
||||
xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
|
||||
{
|
||||
for (int i = 0; handler_info[i].name != NULL; i++) {
|
||||
Py_VISIT(op->handlers[i]);
|
||||
}
|
||||
Py_VISIT(Py_TYPE(op));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xmlparse_clear(xmlparseobject *op)
|
||||
{
|
||||
clear_handlers(op, 0);
|
||||
Py_CLEAR(op->intern);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
xmlparse_dealloc(xmlparseobject *self)
|
||||
{
|
||||
int i;
|
||||
PyObject_GC_UnTrack(self);
|
||||
if (self->itself != NULL)
|
||||
XML_ParserFree(self->itself);
|
||||
self->itself = NULL;
|
||||
(void)xmlparse_clear(self);
|
||||
|
||||
if (self->handlers != NULL) {
|
||||
for (i = 0; handler_info[i].name != NULL; i++)
|
||||
Py_CLEAR(self->handlers[i]);
|
||||
PyMem_Free(self->handlers);
|
||||
self->handlers = NULL;
|
||||
}
|
||||
|
@ -1202,7 +1217,6 @@ xmlparse_dealloc(xmlparseobject *self)
|
|||
PyMem_Free(self->buffer);
|
||||
self->buffer = NULL;
|
||||
}
|
||||
Py_XDECREF(self->intern);
|
||||
PyTypeObject *tp = Py_TYPE(self);
|
||||
PyObject_GC_Del(self);
|
||||
Py_DECREF(tp);
|
||||
|
@ -1473,23 +1487,6 @@ static PyGetSetDef xmlparse_getsetlist[] = {
|
|||
#undef XMLPARSE_GETTER_DEF
|
||||
#undef XMLPARSE_GETTER_SETTER_DEF
|
||||
|
||||
static int
|
||||
xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; handler_info[i].name != NULL; i++)
|
||||
Py_VISIT(op->handlers[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xmlparse_clear(xmlparseobject *op)
|
||||
{
|
||||
clear_handlers(op, 0);
|
||||
Py_CLEAR(op->intern);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
|
||||
|
||||
static PyType_Slot _xml_parse_type_spec_slots[] = {
|
||||
|
|
|
@ -102,12 +102,13 @@ new_previous_version(PyTypeObject *ucd_type,
|
|||
Py_UCS4 (*normalization)(Py_UCS4))
|
||||
{
|
||||
PreviousDBVersion *self;
|
||||
self = PyObject_New(PreviousDBVersion, ucd_type);
|
||||
self = PyObject_GC_New(PreviousDBVersion, ucd_type);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
self->name = name;
|
||||
self->getrecord = getrecord;
|
||||
self->normalization = normalization;
|
||||
PyObject_GC_Track(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
|
@ -1435,16 +1436,25 @@ static PyMethodDef unicodedata_functions[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static int
|
||||
ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ucd_dealloc(PreviousDBVersion *self)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(self);
|
||||
PyObject_Free(self);
|
||||
PyObject_GC_UnTrack(self);
|
||||
PyObject_GC_Del(self);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static PyType_Slot ucd_type_slots[] = {
|
||||
{Py_tp_dealloc, ucd_dealloc},
|
||||
{Py_tp_traverse, ucd_traverse},
|
||||
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||
{Py_tp_methods, unicodedata_functions},
|
||||
{Py_tp_members, DB_members},
|
||||
|
@ -1454,7 +1464,8 @@ static PyType_Slot ucd_type_slots[] = {
|
|||
static PyType_Spec ucd_type_spec = {
|
||||
.name = "unicodedata.UCD",
|
||||
.basicsize = sizeof(PreviousDBVersion),
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
|
||||
Py_TPFLAGS_HAVE_GC),
|
||||
.slots = ucd_type_slots
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue