mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
subtype_dealloc(): A more complete fix for critical bug 840829 +
expanded the test case with a piece that needs the more-complete fix. I'll backport this to 2.3 maint.
This commit is contained in:
parent
981a918575
commit
f7f9e9966b
2 changed files with 38 additions and 6 deletions
|
|
@ -639,10 +639,10 @@ subtype_dealloc(PyObject *self)
|
|||
++_PyTrash_delete_nesting;
|
||||
Py_TRASHCAN_SAFE_BEGIN(self);
|
||||
--_PyTrash_delete_nesting;
|
||||
/* DO NOT restore GC tracking at this point. The weakref callback
|
||||
* (if any) may trigger GC, and if self is tracked at that point,
|
||||
* it will look like trash to GC and GC will try to delete it
|
||||
* again. Double-deallocation is a subtle disaster.
|
||||
/* DO NOT restore GC tracking at this point. weakref callbacks
|
||||
* (if any, and whether directly here or indirectly in something we
|
||||
* call) may trigger GC, and if self is tracked at that point, it
|
||||
* will look like trash to GC and GC will try to delete self again.
|
||||
*/
|
||||
|
||||
/* Find the nearest base with a different tp_dealloc */
|
||||
|
|
@ -658,13 +658,15 @@ subtype_dealloc(PyObject *self)
|
|||
|
||||
if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
|
||||
PyObject_ClearWeakRefs(self);
|
||||
_PyObject_GC_TRACK(self); /* We'll untrack for real later */
|
||||
|
||||
/* Maybe call finalizer; exit early if resurrected */
|
||||
if (type->tp_del) {
|
||||
_PyObject_GC_TRACK(self);
|
||||
type->tp_del(self);
|
||||
if (self->ob_refcnt > 0)
|
||||
goto endlabel;
|
||||
goto endlabel; /* resurrected */
|
||||
else
|
||||
_PyObject_GC_UNTRACK(self);
|
||||
}
|
||||
|
||||
/* Clear slots up to the nearest base with a different tp_dealloc */
|
||||
|
|
@ -689,6 +691,7 @@ subtype_dealloc(PyObject *self)
|
|||
}
|
||||
|
||||
/* Finalize GC if the base doesn't do GC and we do */
|
||||
_PyObject_GC_TRACK(self);
|
||||
if (!PyType_IS_GC(base))
|
||||
_PyObject_GC_UNTRACK(self);
|
||||
|
||||
|
|
@ -730,6 +733,16 @@ subtype_dealloc(PyObject *self)
|
|||
trashcan begin
|
||||
GC track
|
||||
|
||||
Q. Why did the last question say "immediately GC-track again"?
|
||||
It's nowhere near immediately.
|
||||
|
||||
A. Because the code *used* to re-track immediately. Bad Idea.
|
||||
self has a refcount of 0, and if gc ever gets its hands on it
|
||||
(which can happen if any weakref callback gets invoked), it
|
||||
looks like trash to gc too, and gc also tries to delete self
|
||||
then. But we're already deleting self. Double dealloction is
|
||||
a subtle disaster.
|
||||
|
||||
Q. Why the bizarre (net-zero) manipulation of
|
||||
_PyTrash_delete_nesting around the trashcan macros?
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue