[Python-checkins] python/dist/src/Objects typeobject.c,2.165,2.166

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Tue, 06 Aug 2002 14:41:47 -0700


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

Modified Files:
	typeobject.c 
Log Message:
Fix SF bug 574207 (chained __slots__ dealloc segfault).

This is inspired by SF patch 581742 (by Jonathan Hogg, who also
submitted the bug report, and two other suggested patches), but
separates the non-GC case from the GC case to avoid testing for GC
several times.

Had to fix an assert() from call_finalizer() that asserted that the
object wasn't untracked, because it's possible that the object isn't
GC'ed!


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.165
retrieving revision 2.166
diff -C2 -d -r2.165 -r2.166
*** typeobject.c	1 Aug 2002 14:38:53 -0000	2.165
--- typeobject.c	6 Aug 2002 21:41:44 -0000	2.166
***************
*** 402,406 ****
  		self->ob_refcnt = refcnt;
  	}
! 	assert(_Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
  	/* If Py_REF_DEBUG, the original decref dropped _Py_RefTotal, but
  	 * _Py_NewReference bumped it again, so that's a wash.
--- 402,407 ----
  		self->ob_refcnt = refcnt;
  	}
! 	assert(!PyType_IS_GC(self->ob_type) ||
! 	       _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
  	/* If Py_REF_DEBUG, the original decref dropped _Py_RefTotal, but
  	 * _Py_NewReference bumped it again, so that's a wash.
***************
*** 424,429 ****
  	destructor basedealloc;
  
! 	/* This exists so we can DECREF self->ob_type */
  
  	if (call_finalizer(self) < 0)
  		return;
--- 425,472 ----
  	destructor basedealloc;
  
! 	/* Extract the type; we expect it to be a heap type */
! 	type = self->ob_type;
! 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
! 
! 	/* Test whether the type has GC exactly once */
! 
! 	if (!PyType_IS_GC(type)) {
! 		/* It's really rare to find a dynamic type that doesn't have
! 		   GC; it can only happen when deriving from 'object' and not
! 		   adding any slots or instance variables.  This allows
! 		   certain simplifications: there's no need to call
! 		   clear_slots(), or DECREF the dict, or clear weakrefs. */
! 
! 		/* Maybe call finalizer; exit early if resurrected */
! 		if (call_finalizer(self) < 0)
! 			return;
! 
! 		/* Find the nearest base with a different tp_dealloc */
! 		base = type;
! 		while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
! 			assert(base->ob_size == 0);
! 			base = base->tp_base;
! 			assert(base);
! 		}
! 
! 		/* Call the base tp_dealloc() */
! 		assert(basedealloc);
! 		basedealloc(self);
! 
! 		/* Can't reference self beyond this point */
! 		Py_DECREF(type);
! 
! 		/* Done */
! 		return;
! 	}
  
+ 	/* We get here only if the type has GC */
+ 
+ 	/* UnTrack and re-Track around the trashcan macro, alas */
+ 	_PyObject_GC_UNTRACK(self);
+ 	Py_TRASHCAN_SAFE_BEGIN(self);
+ 	_PyObject_GC_TRACK(self); /* We'll untrack for real later */
+ 
+ 	/* Maybe call finalizer; exit early if resurrected */
  	if (call_finalizer(self) < 0)
  		return;
***************
*** 431,435 ****
  	/* Find the nearest base with a different tp_dealloc
  	   and clear slots while we're at it */
- 	type = self->ob_type;
  	base = type;
  	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
--- 474,477 ----
***************
*** 457,461 ****
  
  	/* Finalize GC if the base doesn't do GC and we do */
! 	if (PyType_IS_GC(type) && !PyType_IS_GC(base))
  		_PyObject_GC_UNTRACK(self);
  
--- 499,503 ----
  
  	/* Finalize GC if the base doesn't do GC and we do */
! 	if (!PyType_IS_GC(base))
  		_PyObject_GC_UNTRACK(self);
  
***************
*** 465,471 ****
  
  	/* Can't reference self beyond this point */
! 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
! 		Py_DECREF(type);
! 	}
  }
  
--- 507,513 ----
  
  	/* Can't reference self beyond this point */
! 	Py_DECREF(type);
! 
! 	Py_TRASHCAN_SAFE_END(self);
  }
  
***************
*** 2808,2812 ****
  	return Py_None;
  }
!   
  static PyObject *
  wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped)
--- 2850,2854 ----
  	return Py_None;
  }
! 
  static PyObject *
  wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped)
***************
*** 2993,2997 ****
  		return -1;
  	if (len < 0) {
! 		PyErr_SetString(PyExc_ValueError, 
  				"__len__() should return >= 0");
  		return -1;
--- 3035,3039 ----
  		return -1;
  	if (len < 0) {
! 		PyErr_SetString(PyExc_ValueError,
  				"__len__() should return >= 0");
  		return -1;
***************
*** 4040,4044 ****
  }
  
! static int recurse_down_subclasses(PyTypeObject *type, slotdef **pp, 
  				   PyObject *name);
  
--- 4082,4086 ----
  }
  
! static int recurse_down_subclasses(PyTypeObject *type, slotdef **pp,
  				   PyObject *name);