[Python-checkins] python/dist/src/Objects typeobject.c,2.250,2.251

tim_one at users.sourceforge.net tim_one at users.sourceforge.net
Wed Nov 12 15:43:30 EST 2003


Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1:/tmp/cvs-serv32659/Objects

Modified Files:
	typeobject.c 
Log Message:
SF bug 840829:  weakref callbacks and gc corrupt memory.

subtype_dealloc():  This left the dying object exposed to gc, so that
if cyclic gc triggered during the weakref callback, gc tried to delete
the dying object a second time.  That's a disaster.  subtype_dealloc()
had a (I hope!) unique problem here, as every normal dealloc routine
untracks the object (from gc) before fiddling with weakrefs etc.  But
subtype_dealloc has obscure technical reasons for re-registering the
dying object with gc (already explained in a large comment block at
the bottom of the function).

The fix amounts to simply refraining from reregistering the dying object
with gc until after the weakref callback (if any) has been called.

This is a critical bug (hard to predict, and causes seemingly random
memory corruption when it occurs).  I'll backport it to 2.3 later.


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.250
retrieving revision 2.251
diff -C2 -d -r2.250 -r2.251
*** typeobject.c	20 Oct 2003 14:01:54 -0000	2.250
--- typeobject.c	12 Nov 2003 20:43:28 -0000	2.251
***************
*** 640,644 ****
  	Py_TRASHCAN_SAFE_BEGIN(self);
  	--_PyTrash_delete_nesting;
! 	_PyObject_GC_TRACK(self); /* We'll untrack for real later */
  
  	/* Find the nearest base with a different tp_dealloc */
--- 640,648 ----
  	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.
! 	 */
  
  	/* Find the nearest base with a different tp_dealloc */
***************
*** 655,658 ****
--- 659,663 ----
  	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 */





More information about the Python-checkins mailing list