diff --git a/Misc/NEWS b/Misc/NEWS index 6367afd7fd5..5dea7f36056 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,13 @@ Library - Issue #24369: Defend against key-changes during iteration. +Tests +----- + +- Issue #24373: _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) + What's New in Python 3.5.0 beta 2? ================================== diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 7b98be2b8ef..2919687e112 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -12,11 +12,18 @@ typedef struct { /* Example methods */ -static void -Example_dealloc(ExampleObject *self) +static int +Example_traverse(ExampleObject *self, visitproc visit, void *arg) { - Py_XDECREF(self->x_attr); - PyObject_Del(self); + Py_VISIT(self->x_attr); + return 0; +} + +static int +Example_finalize(ExampleObject *self) +{ + Py_CLEAR(self->x_attr); + return 0; } static PyObject * @@ -74,7 +81,8 @@ Example_setattr(ExampleObject *self, char *name, PyObject *v) static PyType_Slot Example_Type_slots[] = { {Py_tp_doc, "The Example type"}, - {Py_tp_dealloc, Example_dealloc}, + {Py_tp_finalize, Example_finalize}, + {Py_tp_traverse, Example_traverse}, {Py_tp_getattro, Example_getattro}, {Py_tp_setattr, Example_setattr}, {Py_tp_methods, Example_methods}, @@ -85,7 +93,7 @@ static PyType_Spec Example_Type_spec = { "_testimportexec.Example", sizeof(ExampleObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, Example_Type_slots }; diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 604456bffe6..40c176063db 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -40,11 +40,18 @@ newXxoObject(PyObject *arg) /* Xxo methods */ -static void -Xxo_dealloc(XxoObject *self) +static int +Xxo_traverse(XxoObject *self, visitproc visit, void *arg) { - Py_XDECREF(self->x_attr); - ((freefunc)PyType_GetSlot(Py_TYPE(self), Py_tp_free))(self); + Py_VISIT(self->x_attr); + return 0; +} + +static int +Xxo_finalize(XxoObject *self) +{ + Py_CLEAR(self->x_attr); + return 0; } static PyObject * @@ -102,7 +109,8 @@ Xxo_setattr(XxoObject *self, char *name, PyObject *v) static PyType_Slot Xxo_Type_slots[] = { {Py_tp_doc, "The Xxo type"}, - {Py_tp_dealloc, Xxo_dealloc}, + {Py_tp_traverse, Xxo_traverse}, + {Py_tp_finalize, Xxo_finalize}, {Py_tp_getattro, Xxo_getattro}, {Py_tp_setattr, Xxo_setattr}, {Py_tp_methods, Xxo_methods}, @@ -113,7 +121,7 @@ static PyType_Spec Xxo_Type_spec = { "xxlimited.Xxo", sizeof(XxoObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, Xxo_Type_slots }; @@ -247,6 +255,12 @@ xx_modexec(PyObject *m) Py_INCREF(ErrorObject); PyModule_AddObject(m, "error", ErrorObject); + /* Add Xxo */ + o = PyType_FromSpec(&Xxo_Type_spec); + if (o == NULL) + goto fail; + PyModule_AddObject(m, "Xxo", o); + /* Add Str */ o = PyType_FromSpec(&Str_Type_spec); if (o == NULL)