mirror of
https://github.com/python/cpython.git
synced 2025-07-15 23:35:23 +00:00
New comments. Rewrote has_finalizer() as a sequence of ifs instead of
squashed-together conditional operators; makes it much easier to step thru in the debugger, and to set a breakpoint on the only dangerous path.
This commit is contained in:
parent
93ad66dea9
commit
86b993b6cf
1 changed files with 21 additions and 6 deletions
|
@ -339,13 +339,26 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
|
|||
}
|
||||
}
|
||||
|
||||
/* return true if object has a finalization method */
|
||||
/* Return true if object has a finalization method.
|
||||
* CAUTION: An instance of an old-style class has to be checked for a
|
||||
*__del__ method, and that can cause arbitrary Python code to get executed
|
||||
* via the class's __getattr__ hook (if any). This function can therefore
|
||||
* mutate the object graph, and that's been the source of subtle bugs.
|
||||
*/
|
||||
static int
|
||||
has_finalizer(PyObject *op)
|
||||
{
|
||||
return PyInstance_Check(op) ? PyObject_HasAttr(op, delstr) :
|
||||
PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE) ?
|
||||
op->ob_type->tp_del != NULL : 0;
|
||||
if (PyInstance_Check(op)) {
|
||||
/* This is the dangerous path: hasattr can invoke
|
||||
* the class __getattr__(), and that can do anything.
|
||||
*/
|
||||
assert(delstr != NULL);
|
||||
return PyObject_HasAttr(op, delstr);
|
||||
}
|
||||
else if (PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE))
|
||||
return op->ob_type->tp_del != NULL;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Move all objects out of unreachable and into collectable or finalizers.
|
||||
|
@ -586,8 +599,10 @@ collect(int generation)
|
|||
* instance objects with __del__ methods.
|
||||
*
|
||||
* Move each object into the collectable set or the finalizers set.
|
||||
* It's possible that a classic class with a getattr() hook will
|
||||
* be revived or deallocated in this step.
|
||||
* Because we need to check for __del__ methods on instances of
|
||||
* classic classes, arbitrary Python code may get executed by
|
||||
* getattr hooks: that may resurrect or deallocate (via refcount
|
||||
* falling to 0) unreachable objects, so this is very delicate.
|
||||
*/
|
||||
gc_list_init(&collectable);
|
||||
gc_list_init(&finalizers);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue