[Patches] GC infrastructure patch 1 (tp_recurse, tp_clear)

Jeremy Hylton jeremy@beopen.com
Wed, 21 Jun 2000 10:16:11 -0400 (EDT)


>>>>> "MAL" == M -A Lemburg <mal@lemburg.com> writes:

  MAL> Neil Schemenauer wrote:
  [...]
  >> Can anyone think of a use for the return value?  I guess it could
  >> be added back if someone found a use of it.

  MAL> ... how about -1 for errors and 0 for normal operation. If you
  MAL> don't provide a way to report errors then cleanup actions won't
  MAL> be able to terminate prematurely.

I'm still not convinced that a return value is useful.  Here's an
example of a function that uses the recurse code and visit code.  Note
that in the first function the return value is explicitly cast to
void.  It seems that it we were going to be careful about adding
return values, we would need to put some error checking here and
explicitly deal with the error return.

static void
move_root_reachable(PyGCInfo *reachable)
{
	recurseproc recurse;
	PyGCInfo *gc = reachable->gc_next;
	for (; gc != reachable; gc=gc->gc_next) {
		/* careful, reachable list is growing here */
		PyObject *op = PyGC_OBJ(gc);
		recurse = op->ob_type->tp_recurse;
		(void) recurse(op,
			       (visitproc)visit_reachable,
			       (void *)reachable);
	}
}

static int
visit_reachable(PyObject *op, PyGCInfo *roots)
{
	PyGCInfo *gc = PyGC_INFO(op);
	if (gc && gc->gc_refs != GC_MOVED) {
		gc_list_remove(gc);
		gc_list_append(gc, roots);
		gc->gc_refs = GC_MOVED;
	}
	return 1;
}

The recurse function called in the 1st function above will return an
error only if the visit function returns an error.  The visit function
never returns an error.  (In fact, none of the visit functions return
an error.)

On the one hand, it seems appropriate to by careful about error
checking.  Each function could return -1 for error and 0 for success
(or use some other convention), but then all of the code ought to
check the return values and do something appropriate when an error is
returned.

On the other hand, none of the code that is currently implemented
looks like it could return an error.  The visit_reachable function
above is just doing a bunch of pointer operations.  The gc_list_
functions do a few pointer assignments and have no return value.  If
there is going to be a problem, it seems it would be caused by
corruption of a PyObject caused by an error elsewhere (perhaps an
extension). 

Better error checking -- just sanity checks -- in the GC code might be
helpful, along with a mechanism to print out errors or exceptions that
get raised during the traversal.

So, concretely I see two courses of action:

1. Change the class and function recurse functions to check the return
value of the visit calls they make and return an error if visit
returns an error.  Then change all the places that call the recurse
functions to report an error if the recurse function reports an error.
(Not sure how to report the error.)

2. Change the visit and recurse functions to have no return value
(void) and worry about error checking later.

Jeremy