classification
Title: A tp_dealloc of a subclassed class cannot resurrect an object
Type: enhancement Stage: needs patch
Components: Interpreter Core Versions: Python 3.2
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, krisvale, pitrou
Priority: normal Keywords:

Created on 2010-03-23 13:28 by krisvale, last changed 2010-08-09 18:38 by terry.reedy.

Messages (2)
msg101580 - (view) Author: Kristján Valur Jónsson (krisvale) * Date: 2010-03-23 13:28
The tp_dealloc of a type can chose to resurrect an object.  the subtype_dealloc() in typeobject.c does this when it calls the tp_del() member and it has increased the refcount.

The problem is, that if you subclass a custom C object, and that C object's tp_dealloc() chooses to resurrect a dying object, that doesn't go well with subtype_dealloc().

After calling basedealloc() (line 1002 in typeobject.c), the object's type is decrefed.  But if the object was resurrected by basedealloc() this shouldn't have been done.  The object will be alive, but the type will be missing a reference.  This will cause a crash later.

This could be fixable if we knew somehow after calling basedealloc() if the object were still alive.  But we cannot check "self" because it may have died.

The only way out of this conundrum that I can see is to change the signature of tp_dealloc() to return a flag, whether it did actually delete the object or not.

Of course, I see no easy way around not clearing the slots, but the clearing of the dict could be postponed until after the call to basedealloc().

Since tp_dealloc _can_ resurrect objects (subtype_dealloc does it), subclassing such objects should work, and not crash the interpreter if the base class' dp_dealloc() decides to do so.
No suggested
msg101585 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-03-23 15:25
Indeed. The io module has had to circumvent this and uses the following snippet when resurrecting an instance of a subclass of one of its types (see iobase_dealloc() in Modules/_io/iobase.c):

        /* When called from a heap type's dealloc, the type will be
           decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
        if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE))
            Py_INCREF(Py_TYPE(self));
        return;


I agree it would be nice to have an automatic way of handling this. I don't see an obvious solution, though.
History
Date User Action Args
2010-08-09 18:38:19terry.reedysetversions: - Python 2.7
2010-03-23 15:25:38pitrouset
nosy: + pitrou, benjamin.peterson
versions: + Python 3.2
messages: + msg101585
priority: normal
components: + Interpreter Core
type: crash -> enhancement
stage: needs patch
2010-03-23 13:28:30krisvalecreate