@@ -639,10 +639,10 @@ subtype_dealloc(PyObject *self)
639639 ++ _PyTrash_delete_nesting ;
640640 Py_TRASHCAN_SAFE_BEGIN (self );
641641 -- _PyTrash_delete_nesting ;
642- /* DO NOT restore GC tracking at this point. The weakref callback
643- * (if any) may trigger GC , and if self is tracked at that point,
644- * it will look like trash to GC and GC will try to delete it
645- * again. Double-deallocation is a subtle disaster .
642+ /* DO NOT restore GC tracking at this point. weakref callbacks
643+ * (if any, and whether directly here or indirectly in something we
644+ * call) may trigger GC, and if self is tracked at that point, it
645+ * will look like trash to GC and GC will try to delete self again .
646646 */
647647
648648 /* Find the nearest base with a different tp_dealloc */
@@ -658,13 +658,15 @@ subtype_dealloc(PyObject *self)
658658
659659 if (type -> tp_weaklistoffset && !base -> tp_weaklistoffset )
660660 PyObject_ClearWeakRefs (self );
661- _PyObject_GC_TRACK (self ); /* We'll untrack for real later */
662661
663662 /* Maybe call finalizer; exit early if resurrected */
664663 if (type -> tp_del ) {
664+ _PyObject_GC_TRACK (self );
665665 type -> tp_del (self );
666666 if (self -> ob_refcnt > 0 )
667- goto endlabel ;
667+ goto endlabel ; /* resurrected */
668+ else
669+ _PyObject_GC_UNTRACK (self );
668670 }
669671
670672 /* Clear slots up to the nearest base with a different tp_dealloc */
@@ -689,6 +691,7 @@ subtype_dealloc(PyObject *self)
689691 }
690692
691693 /* Finalize GC if the base doesn't do GC and we do */
694+ _PyObject_GC_TRACK (self );
692695 if (!PyType_IS_GC (base ))
693696 _PyObject_GC_UNTRACK (self );
694697
@@ -730,6 +733,16 @@ subtype_dealloc(PyObject *self)
730733 trashcan begin
731734 GC track
732735
736+ Q. Why did the last question say "immediately GC-track again"?
737+ It's nowhere near immediately.
738+
739+ A. Because the code *used* to re-track immediately. Bad Idea.
740+ self has a refcount of 0, and if gc ever gets its hands on it
741+ (which can happen if any weakref callback gets invoked), it
742+ looks like trash to gc too, and gc also tries to delete self
743+ then. But we're already deleting self. Double dealloction is
744+ a subtle disaster.
745+
733746 Q. Why the bizarre (net-zero) manipulation of
734747 _PyTrash_delete_nesting around the trashcan macros?
735748
0 commit comments