]> granicus.if.org Git - python/commitdiff
Make staticmethods and classmethods participate in GC.
authorJeremy Hylton <jeremy@alum.mit.edu>
Tue, 8 Apr 2003 21:28:47 +0000 (21:28 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Tue, 8 Apr 2003 21:28:47 +0000 (21:28 +0000)
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.

Objects/funcobject.c

index 6f0fa268562902d83c1c2e9d38355240d893a1fb..af34392fda8e74adedf4016ff4b3020aba110eee 100644 (file)
@@ -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 *