summaryrefslogtreecommitdiffstats
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2003-04-08 21:28:47 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2003-04-08 21:28:47 (GMT)
commit400d8ee6fa59bd2969c67cbd1e4f6d9663edb090 (patch)
treeaefe767a61d9c1e08230262f3661f6cc7e032da6 /Objects/funcobject.c
parent547eb42d75c888fa5ac43275d3cf874099ea0d78 (diff)
downloadcpython-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.c53
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 *