Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 59af59c

Browse filesBrowse files
author
Erlend Egeberg Aasland
authored
bpo-42972: Fully support GC for pyexpat, unicodedata, and dbm/gdbm heap types (pythonGH-26376)
* bpo-42972: pyexpat * bpo-42972: unicodedata * bpo-42972: dbm/gdbm
1 parent fbff538 commit 59af59c
Copy full SHA for 59af59c

File tree

5 files changed

+69
-35
lines changed
Filter options

5 files changed

+69
-35
lines changed

‎Modules/_dbmmodule.c

Copy file name to clipboardExpand all lines: Modules/_dbmmodule.c
+15-5Lines changed: 15 additions & 5 deletions
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

Copy file name to clipboardExpand all lines: Modules/_gdbmmodule.c
+13-2Lines changed: 13 additions & 2 deletions
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

Copy file name to clipboardExpand all lines: Modules/_lsprof.c
+9-4Lines changed: 9 additions & 4 deletions
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

Copy file name to clipboardExpand all lines: Modules/pyexpat.c
+18-21Lines changed: 18 additions & 21 deletions
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

Copy file name to clipboardExpand all lines: Modules/unicodedata.c
+14-3Lines changed: 14 additions & 3 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.