Skip to content

Commit 53f9502

Browse files
committed
Issue #24373: Eliminate PEP 489 test refleaks
_testmultiphase and xxlimited now use tp_traverse and tp_finalize to avoid reference leaks encountered when combining tp_dealloc with PyType_FromSpec (see issue #16690 for details)
1 parent 4fabf02 commit 53f9502

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed

Misc/NEWS

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ Library
2929

3030
- Issue #24369: Defend against key-changes during iteration.
3131

32+
Tests
33+
-----
34+
35+
- Issue #24373: _testmultiphase and xxlimited now use tp_traverse and
36+
tp_finalize to avoid reference leaks encountered when combining tp_dealloc
37+
with PyType_FromSpec (see issue #16690 for details)
38+
3239

3340
What's New in Python 3.5.0 beta 2?
3441
==================================

Modules/_testmultiphase.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@ typedef struct {
1212

1313
/* Example methods */
1414

15-
static void
16-
Example_dealloc(ExampleObject *self)
15+
static int
16+
Example_traverse(ExampleObject *self, visitproc visit, void *arg)
1717
{
18-
Py_XDECREF(self->x_attr);
19-
PyObject_Del(self);
18+
Py_VISIT(self->x_attr);
19+
return 0;
20+
}
21+
22+
static int
23+
Example_finalize(ExampleObject *self)
24+
{
25+
Py_CLEAR(self->x_attr);
26+
return 0;
2027
}
2128

2229
static PyObject *
@@ -74,7 +81,8 @@ Example_setattr(ExampleObject *self, char *name, PyObject *v)
7481

7582
static PyType_Slot Example_Type_slots[] = {
7683
{Py_tp_doc, "The Example type"},
77-
{Py_tp_dealloc, Example_dealloc},
84+
{Py_tp_finalize, Example_finalize},
85+
{Py_tp_traverse, Example_traverse},
7886
{Py_tp_getattro, Example_getattro},
7987
{Py_tp_setattr, Example_setattr},
8088
{Py_tp_methods, Example_methods},
@@ -85,7 +93,7 @@ static PyType_Spec Example_Type_spec = {
8593
"_testimportexec.Example",
8694
sizeof(ExampleObject),
8795
0,
88-
Py_TPFLAGS_DEFAULT,
96+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
8997
Example_Type_slots
9098
};
9199

Modules/xxlimited.c

+20-6
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@ newXxoObject(PyObject *arg)
4040

4141
/* Xxo methods */
4242

43-
static void
44-
Xxo_dealloc(XxoObject *self)
43+
static int
44+
Xxo_traverse(XxoObject *self, visitproc visit, void *arg)
45+
{
46+
Py_VISIT(self->x_attr);
47+
return 0;
48+
}
49+
50+
static int
51+
Xxo_finalize(XxoObject *self)
4552
{
46-
Py_XDECREF(self->x_attr);
47-
((freefunc)PyType_GetSlot(Py_TYPE(self), Py_tp_free))(self);
53+
Py_CLEAR(self->x_attr);
54+
return 0;
4855
}
4956

5057
static PyObject *
@@ -102,7 +109,8 @@ Xxo_setattr(XxoObject *self, char *name, PyObject *v)
102109

103110
static PyType_Slot Xxo_Type_slots[] = {
104111
{Py_tp_doc, "The Xxo type"},
105-
{Py_tp_dealloc, Xxo_dealloc},
112+
{Py_tp_traverse, Xxo_traverse},
113+
{Py_tp_finalize, Xxo_finalize},
106114
{Py_tp_getattro, Xxo_getattro},
107115
{Py_tp_setattr, Xxo_setattr},
108116
{Py_tp_methods, Xxo_methods},
@@ -113,7 +121,7 @@ static PyType_Spec Xxo_Type_spec = {
113121
"xxlimited.Xxo",
114122
sizeof(XxoObject),
115123
0,
116-
Py_TPFLAGS_DEFAULT,
124+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
117125
Xxo_Type_slots
118126
};
119127

@@ -247,6 +255,12 @@ xx_modexec(PyObject *m)
247255
Py_INCREF(ErrorObject);
248256
PyModule_AddObject(m, "error", ErrorObject);
249257

258+
/* Add Xxo */
259+
o = PyType_FromSpec(&Xxo_Type_spec);
260+
if (o == NULL)
261+
goto fail;
262+
PyModule_AddObject(m, "Xxo", o);
263+
250264
/* Add Str */
251265
o = PyType_FromSpec(&Str_Type_spec);
252266
if (o == NULL)

0 commit comments

Comments
 (0)