mirror of https://github.com/python/cpython
Make staticmethods and classmethods participate in GC.
If a class was defined inside a function, used a static or class method, and used super() inside the method body, it would be caught in an uncollectable cycle. (Simplified version: The static/class method object would point to a function object with a closure that referred to the class.) Bugfix candidate.
This commit is contained in:
parent
547eb42d75
commit
400d8ee6fa
|
@ -590,10 +590,29 @@ typedef struct {
|
|||
static void
|
||||
cm_dealloc(classmethod *cm)
|
||||
{
|
||||
_PyObject_GC_UNTRACK((PyObject *)cm);
|
||||
Py_XDECREF(cm->cm_callable);
|
||||
cm->ob_type->tp_free((PyObject *)cm);
|
||||
}
|
||||
|
||||
static int
|
||||
cm_traverse(classmethod *cm, visitproc visit, void *arg)
|
||||
{
|
||||
if (!cm->cm_callable)
|
||||
return 0;
|
||||
return visit(cm->cm_callable, arg);
|
||||
}
|
||||
|
||||
static int
|
||||
cm_clear(classmethod *cm)
|
||||
{
|
||||
Py_XDECREF(cm->cm_callable);
|
||||
cm->cm_callable = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
|
||||
{
|
||||
|
@ -665,10 +684,10 @@ PyTypeObject PyClassMethod_Type = {
|
|||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
|
||||
classmethod_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
(traverseproc)cm_traverse, /* tp_traverse */
|
||||
(inquiry)cm_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
|
@ -684,7 +703,7 @@ PyTypeObject PyClassMethod_Type = {
|
|||
cm_init, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
PyObject_Del, /* tp_free */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
PyObject *
|
||||
|
@ -724,10 +743,28 @@ typedef struct {
|
|||
static void
|
||||
sm_dealloc(staticmethod *sm)
|
||||
{
|
||||
_PyObject_GC_UNTRACK((PyObject *)sm);
|
||||
Py_XDECREF(sm->sm_callable);
|
||||
sm->ob_type->tp_free((PyObject *)sm);
|
||||
}
|
||||
|
||||
static int
|
||||
sm_traverse(staticmethod *sm, visitproc visit, void *arg)
|
||||
{
|
||||
if (!sm->sm_callable)
|
||||
return 0;
|
||||
return visit(sm->sm_callable, arg);
|
||||
}
|
||||
|
||||
static int
|
||||
sm_clear(staticmethod *sm)
|
||||
{
|
||||
Py_XDECREF(sm->sm_callable);
|
||||
sm->sm_callable = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
sm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
|
||||
{
|
||||
|
@ -794,10 +831,10 @@ PyTypeObject PyStaticMethod_Type = {
|
|||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
|
||||
staticmethod_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
(traverseproc)sm_traverse, /* tp_traverse */
|
||||
(inquiry)sm_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
|
@ -813,7 +850,7 @@ PyTypeObject PyStaticMethod_Type = {
|
|||
sm_init, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
PyObject_Del, /* tp_free */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
PyObject *
|
||||
|
|
Loading…
Reference in New Issue