diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2003-04-08 21:28:47 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2003-04-08 21:28:47 (GMT) |
commit | 400d8ee6fa59bd2969c67cbd1e4f6d9663edb090 (patch) | |
tree | aefe767a61d9c1e08230262f3661f6cc7e032da6 /Objects/funcobject.c | |
parent | 547eb42d75c888fa5ac43275d3cf874099ea0d78 (diff) | |
download | cpython-400d8ee6fa59bd2969c67cbd1e4f6d9663edb090.zip cpython-400d8ee6fa59bd2969c67cbd1e4f6d9663edb090.tar.gz cpython-400d8ee6fa59bd2969c67cbd1e4f6d9663edb090.tar.bz2 |
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.
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r-- | Objects/funcobject.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 6f0fa26..af34392 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -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 * |