diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 96d0b0a5cfe6a5..2b4d071b3d1ae1 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -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, }; diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index dc8b8b692c1a3f..98bfa6ab996119 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -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, }; diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index c32699cb8ad580..a0e6afa844086a 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -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, }; diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 7f727a86f5f47d..9b04df36f5201a 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -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[] = { diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 2e8d199de86ca8..a4b8193fbc2300 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -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 };