Skip to content

Commit 59af59c

Browse files
author
Erlend Egeberg Aasland
authored
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
1 parent fbff538 commit 59af59c

File tree

5 files changed

+69
-35
lines changed

5 files changed

+69
-35
lines changed

Modules/_dbmmodule.c

+15-5
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ typedef struct {
6565
static PyObject *
6666
newdbmobject(_dbm_state *state, const char *file, int flags, int mode)
6767
{
68-
dbmobject *dp;
69-
70-
dp = PyObject_New(dbmobject, state->dbm_type);
71-
if (dp == NULL)
68+
dbmobject *dp = PyObject_GC_New(dbmobject, state->dbm_type);
69+
if (dp == NULL) {
7270
return NULL;
71+
}
7372
dp->di_size = -1;
7473
dp->flags = flags;
74+
PyObject_GC_Track(dp);
75+
7576
/* See issue #19296 */
7677
if ( (dp->di_dbm = dbm_open((char *)file, flags, mode)) == 0 ) {
7778
PyErr_SetFromErrnoWithFilename(state->dbm_error, file);
@@ -82,10 +83,17 @@ newdbmobject(_dbm_state *state, const char *file, int flags, int mode)
8283
}
8384

8485
/* Methods */
86+
static int
87+
dbm_traverse(dbmobject *dp, visitproc visit, void *arg)
88+
{
89+
Py_VISIT(Py_TYPE(dp));
90+
return 0;
91+
}
8592

8693
static void
8794
dbm_dealloc(dbmobject *dp)
8895
{
96+
PyObject_GC_UnTrack(dp);
8997
if (dp->di_dbm) {
9098
dbm_close(dp->di_dbm);
9199
}
@@ -397,6 +405,7 @@ static PyMethodDef dbm_methods[] = {
397405

398406
static PyType_Slot dbmtype_spec_slots[] = {
399407
{Py_tp_dealloc, dbm_dealloc},
408+
{Py_tp_traverse, dbm_traverse},
400409
{Py_tp_methods, dbm_methods},
401410
{Py_sq_contains, dbm_contains},
402411
{Py_mp_length, dbm_length},
@@ -413,7 +422,8 @@ static PyType_Spec dbmtype_spec = {
413422
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
414423
// which prevents to create a subclass.
415424
// So calling PyType_GetModuleState() in this file is always safe.
416-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
425+
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
426+
Py_TPFLAGS_HAVE_GC),
417427
.slots = dbmtype_spec_slots,
418428
};
419429

Modules/_gdbmmodule.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,14 @@ nextkey, reorganize, and sync.");
7474
static PyObject *
7575
newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
7676
{
77-
gdbmobject *dp = PyObject_New(gdbmobject, state->gdbm_type);
77+
gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type);
7878
if (dp == NULL) {
7979
return NULL;
8080
}
8181
dp->di_size = -1;
8282
errno = 0;
83+
PyObject_GC_Track(dp);
84+
8385
if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
8486
if (errno != 0) {
8587
PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
@@ -94,10 +96,17 @@ newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
9496
}
9597

9698
/* Methods */
99+
static int
100+
gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
101+
{
102+
Py_VISIT(Py_TYPE(dp));
103+
return 0;
104+
}
97105

98106
static void
99107
gdbm_dealloc(gdbmobject *dp)
100108
{
109+
PyObject_GC_UnTrack(dp);
101110
if (dp->di_dbm) {
102111
gdbm_close(dp->di_dbm);
103112
}
@@ -554,6 +563,7 @@ static PyMethodDef gdbm_methods[] = {
554563

555564
static PyType_Slot gdbmtype_spec_slots[] = {
556565
{Py_tp_dealloc, gdbm_dealloc},
566+
{Py_tp_traverse, gdbm_traverse},
557567
{Py_tp_methods, gdbm_methods},
558568
{Py_sq_contains, gdbm_contains},
559569
{Py_mp_length, gdbm_length},
@@ -570,7 +580,8 @@ static PyType_Spec gdbmtype_spec = {
570580
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
571581
// which prevents to create a subclass.
572582
// So calling PyType_GetModuleState() in this file is always safe.
573-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
583+
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
584+
Py_TPFLAGS_HAVE_GC),
574585
.slots = gdbmtype_spec_slots,
575586
};
576587

Modules/_lsprof.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,13 @@ profiler_clear(ProfilerObject *pObj, PyObject* noarg)
731731
Py_RETURN_NONE;
732732
}
733733

734+
static int
735+
profiler_traverse(ProfilerObject *op, visitproc visit, void *arg)
736+
{
737+
Py_VISIT(Py_TYPE(op));
738+
return 0;
739+
}
740+
734741
static void
735742
profiler_dealloc(ProfilerObject *op)
736743
{
@@ -798,16 +805,14 @@ static PyType_Slot _lsprof_profiler_type_spec_slots[] = {
798805
{Py_tp_methods, profiler_methods},
799806
{Py_tp_dealloc, profiler_dealloc},
800807
{Py_tp_init, profiler_init},
801-
{Py_tp_alloc, PyType_GenericAlloc},
802-
{Py_tp_new, PyType_GenericNew},
803-
{Py_tp_free, PyObject_Del},
808+
{Py_tp_traverse, profiler_traverse},
804809
{0, 0}
805810
};
806811

807812
static PyType_Spec _lsprof_profiler_type_spec = {
808813
.name = "_lsprof.Profiler",
809814
.basicsize = sizeof(ProfilerObject),
810-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
815+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
811816
.slots = _lsprof_profiler_type_spec_slots,
812817
};
813818

Modules/pyexpat.c

+18-21
Original file line numberDiff line numberDiff line change
@@ -1182,27 +1182,41 @@ newxmlparseobject(pyexpat_state *state, const char *encoding,
11821182
return (PyObject*)self;
11831183
}
11841184

1185+
static int
1186+
xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
1187+
{
1188+
for (int i = 0; handler_info[i].name != NULL; i++) {
1189+
Py_VISIT(op->handlers[i]);
1190+
}
1191+
Py_VISIT(Py_TYPE(op));
1192+
return 0;
1193+
}
1194+
1195+
static int
1196+
xmlparse_clear(xmlparseobject *op)
1197+
{
1198+
clear_handlers(op, 0);
1199+
Py_CLEAR(op->intern);
1200+
return 0;
1201+
}
11851202

11861203
static void
11871204
xmlparse_dealloc(xmlparseobject *self)
11881205
{
1189-
int i;
11901206
PyObject_GC_UnTrack(self);
11911207
if (self->itself != NULL)
11921208
XML_ParserFree(self->itself);
11931209
self->itself = NULL;
1210+
(void)xmlparse_clear(self);
11941211

11951212
if (self->handlers != NULL) {
1196-
for (i = 0; handler_info[i].name != NULL; i++)
1197-
Py_CLEAR(self->handlers[i]);
11981213
PyMem_Free(self->handlers);
11991214
self->handlers = NULL;
12001215
}
12011216
if (self->buffer != NULL) {
12021217
PyMem_Free(self->buffer);
12031218
self->buffer = NULL;
12041219
}
1205-
Py_XDECREF(self->intern);
12061220
PyTypeObject *tp = Py_TYPE(self);
12071221
PyObject_GC_Del(self);
12081222
Py_DECREF(tp);
@@ -1473,23 +1487,6 @@ static PyGetSetDef xmlparse_getsetlist[] = {
14731487
#undef XMLPARSE_GETTER_DEF
14741488
#undef XMLPARSE_GETTER_SETTER_DEF
14751489

1476-
static int
1477-
xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
1478-
{
1479-
int i;
1480-
for (i = 0; handler_info[i].name != NULL; i++)
1481-
Py_VISIT(op->handlers[i]);
1482-
return 0;
1483-
}
1484-
1485-
static int
1486-
xmlparse_clear(xmlparseobject *op)
1487-
{
1488-
clear_handlers(op, 0);
1489-
Py_CLEAR(op->intern);
1490-
return 0;
1491-
}
1492-
14931490
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
14941491

14951492
static PyType_Slot _xml_parse_type_spec_slots[] = {

Modules/unicodedata.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,13 @@ new_previous_version(PyTypeObject *ucd_type,
102102
Py_UCS4 (*normalization)(Py_UCS4))
103103
{
104104
PreviousDBVersion *self;
105-
self = PyObject_New(PreviousDBVersion, ucd_type);
105+
self = PyObject_GC_New(PreviousDBVersion, ucd_type);
106106
if (self == NULL)
107107
return NULL;
108108
self->name = name;
109109
self->getrecord = getrecord;
110110
self->normalization = normalization;
111+
PyObject_GC_Track(self);
111112
return (PyObject*)self;
112113
}
113114

@@ -1435,16 +1436,25 @@ static PyMethodDef unicodedata_functions[] = {
14351436
{NULL, NULL} /* sentinel */
14361437
};
14371438

1439+
static int
1440+
ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg)
1441+
{
1442+
Py_VISIT(Py_TYPE(self));
1443+
return 0;
1444+
}
1445+
14381446
static void
14391447
ucd_dealloc(PreviousDBVersion *self)
14401448
{
14411449
PyTypeObject *tp = Py_TYPE(self);
1442-
PyObject_Free(self);
1450+
PyObject_GC_UnTrack(self);
1451+
PyObject_GC_Del(self);
14431452
Py_DECREF(tp);
14441453
}
14451454

14461455
static PyType_Slot ucd_type_slots[] = {
14471456
{Py_tp_dealloc, ucd_dealloc},
1457+
{Py_tp_traverse, ucd_traverse},
14481458
{Py_tp_getattro, PyObject_GenericGetAttr},
14491459
{Py_tp_methods, unicodedata_functions},
14501460
{Py_tp_members, DB_members},
@@ -1454,7 +1464,8 @@ static PyType_Slot ucd_type_slots[] = {
14541464
static PyType_Spec ucd_type_spec = {
14551465
.name = "unicodedata.UCD",
14561466
.basicsize = sizeof(PreviousDBVersion),
1457-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
1467+
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
1468+
Py_TPFLAGS_HAVE_GC),
14581469
.slots = ucd_type_slots
14591470
};
14601471

0 commit comments

Comments
 (0)