summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorNeil Schemenauer <nascheme@enme.ucalgary.ca>2001-11-01 17:35:23 (GMT)
committerNeil Schemenauer <nascheme@enme.ucalgary.ca>2001-11-01 17:35:23 (GMT)
commita765c120f6fd3004ad3dbc34771f848b19caf18d (patch)
tree4f5036c2429b2ef82908989b6fe9a01352eaff16 /Modules
parentf49c6f9954aa59e29c8b392347646f95cbf8215a (diff)
downloadcpython-a765c120f6fd3004ad3dbc34771f848b19caf18d.zip
cpython-a765c120f6fd3004ad3dbc34771f848b19caf18d.tar.gz
cpython-a765c120f6fd3004ad3dbc34771f848b19caf18d.tar.bz2
Add has_finalizer predictate function. Use it when deciding which
objects to save in gc.garbage. This should be the last change needed to fix SF bug 477059: "__del__ on new classes vs. GC". Note that this change slightly changes the behavior of the collector. Before, if a cycle was found that contained instances with __del__ methods then all instance objects in that cycle were saved in gc.garbage. Now, only objects with __del__ methods are saved in gc.garbage.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/gcmodule.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index a0522a0..0738eb6 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -226,24 +226,36 @@ move_root_reachable(PyGC_Head *reachable)
}
}
-/* Move all objects with finalizers (instances with __del__) */
-static void
-move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
+/* return true of object has a finalization method */
+static int
+has_finalizer(PyObject *op)
{
- PyGC_Head *next;
- PyGC_Head *gc = unreachable->gc.gc_next;
static PyObject *delstr = NULL;
if (delstr == NULL) {
delstr = PyString_InternFromString("__del__");
if (delstr == NULL)
Py_FatalError("PyGC: can't initialize __del__ string");
}
+ if ((PyInstance_Check(op) ||
+ PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE)) &&
+ PyObject_HasAttr(op, delstr)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/* Move all objects with finalizers (instances with __del__) */
+static void
+move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
+{
+ PyGC_Head *next;
+ PyGC_Head *gc = unreachable->gc.gc_next;
for (; gc != unreachable; gc=next) {
PyObject *op = FROM_GC(gc);
next = gc->gc.gc_next;
- if ((PyInstance_Check(op) ||
- PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE)) &&
- PyObject_HasAttr(op, delstr)) {
+ if (has_finalizer(op)) {
gc_list_remove(gc);
gc_list_append(gc, finalizers);
}
@@ -269,7 +281,7 @@ static void
debug_instance(char *msg, PyInstanceObject *inst)
{
char *cname;
- /* be careful not to create new dictionaries */
+ /* simple version of instance_repr */
PyObject *classname = inst->in_class->cl_name;
if (classname != NULL && PyString_Check(classname))
cname = PyString_AsString(classname);
@@ -302,11 +314,11 @@ handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
for (gc = finalizers->gc.gc_next; gc != finalizers;
gc = finalizers->gc.gc_next) {
PyObject *op = FROM_GC(gc);
- if ((debug & DEBUG_SAVEALL) || PyInstance_Check(op)) {
- /* If SAVEALL is not set then just append
- * instances to the list of garbage. We assume
- * that all objects in the finalizers list are
- * reachable from instances. */
+ if ((debug & DEBUG_SAVEALL) || has_finalizer(op)) {
+ /* If SAVEALL is not set then just append objects with
+ * finalizers to the list of garbage. All objects in
+ * the finalizers list are reachable from those
+ * objects. */
PyList_Append(garbage, op);
}
/* object is now reachable again */