[Python-checkins] CVS: python/dist/src/Modules gcmodule.c,2.11,2.12

Neil Schemenauer python-dev@python.org
Fri, 22 Sep 2000 08:22:41 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory slayer.i.sourceforge.net:/tmp/cvs-serv20515/Modules

Modified Files:
	gcmodule.c 
Log Message:
- Add DEBUG_SAVEALL option.  When enabled all garbage objects found by the
  collector will be saved in gc.garbage.  This is useful for debugging a 
  program that creates reference cycles.

- Fix else statements in gcmodule.c to conform to Python coding standards.



Index: gcmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/gcmodule.c,v
retrieving revision 2.11
retrieving revision 2.12
diff -C2 -r2.11 -r2.12
*** gcmodule.c	2000/09/05 15:44:50	2.11
--- gcmodule.c	2000/09/22 15:22:37	2.12
***************
*** 54,61 ****
  #define DEBUG_INSTANCES		(1<<3) /* print instances */
  #define DEBUG_OBJECTS		(1<<4) /* print other objects */
  #define DEBUG_LEAK		DEBUG_COLLECTABLE | \
  				DEBUG_UNCOLLECTABLE | \
  				DEBUG_INSTANCES | \
! 				DEBUG_OBJECTS
  static int debug;
  
--- 54,63 ----
  #define DEBUG_INSTANCES		(1<<3) /* print instances */
  #define DEBUG_OBJECTS		(1<<4) /* print other objects */
+ #define DEBUG_SAVEALL		(1<<5) /* save all garbage in gc.garbage */
  #define DEBUG_LEAK		DEBUG_COLLECTABLE | \
  				DEBUG_UNCOLLECTABLE | \
  				DEBUG_INSTANCES | \
! 				DEBUG_OBJECTS | \
! 				DEBUG_SAVEALL
  static int debug;
  
***************
*** 101,105 ****
  		/* empty from list */
  		gc_list_init(to);
! 	} else {
  		to->gc_next = from->gc_next;
  		to->gc_next->gc_prev = to;
--- 103,108 ----
  		/* empty from list */
  		gc_list_init(to);
! 	}
! 	else {
  		to->gc_next = from->gc_next;
  		to->gc_next->gc_prev = to;
***************
*** 291,295 ****
  	if ((debug & DEBUG_INSTANCES) && PyInstance_Check(op)) {
  		debug_instance(msg, (PyInstanceObject *)op);
! 	} else if (debug & DEBUG_OBJECTS) {
  		PySys_WriteStderr("gc: %.100s <%.100s %p>\n",
  				  msg, op->ob_type->tp_name, op);
--- 294,299 ----
  	if ((debug & DEBUG_INSTANCES) && PyInstance_Check(op)) {
  		debug_instance(msg, (PyInstanceObject *)op);
! 	}
! 	else if (debug & DEBUG_OBJECTS) {
  		PySys_WriteStderr("gc: %.100s <%.100s %p>\n",
  				  msg, op->ob_type->tp_name, op);
***************
*** 308,318 ****
  			gc = finalizers->gc_next) {
  		PyObject *op = PyObject_FROM_GC(gc);
! 		/* Add all instances to a Python accessible list of garbage */
! 		if (PyInstance_Check(op)) {
  			PyList_Append(garbage, op);
  		}
! 		/* We assume that all objects in finalizers are reachable from
! 		 * instances.  Once we add the instances to the garbage list
! 		 * everything is reachable from Python again. */
  		gc_list_remove(gc);
  		gc_list_append(gc, old);
--- 312,323 ----
  			gc = finalizers->gc_next) {
  		PyObject *op = PyObject_FROM_GC(gc);
! 		if ((debug & DEBUG_SAVEALL) || PyInstance_Check(op)) {
! 			/* If SAVEALL is not set then just append
! 			 * instances to the list of garbage.  We assume
! 			 * that all objects in the finalizers list are
! 			 * reachable from instances. */
  			PyList_Append(garbage, op);
  		}
! 		/* object is now reachable again */ 
  		gc_list_remove(gc);
  		gc_list_append(gc, old);
***************
*** 320,324 ****
  }
  
! /* Break reference cycles by clearing the containers involved.  This is
   * tricky business as the lists can be changing and we don't know which
   * objects may be freed.  It is possible I screwed something up here. */
--- 325,329 ----
  }
  
! /* Break reference cycles by clearing the containers involved.	This is
   * tricky business as the lists can be changing and we don't know which
   * objects may be freed.  It is possible I screwed something up here. */
***************
*** 331,345 ****
  		PyGC_Head *gc = unreachable->gc_next;
  		PyObject *op = PyObject_FROM_GC(gc);
! 		/*
! 		PyList_Append(garbage, op);
! 		*/
! 		if ((clear = op->ob_type->tp_clear) != NULL) {
! 			Py_INCREF(op);
! 			clear((PyObject *)op);
! 			Py_DECREF(op);
  		}
! 		/* only try to call tp_clear once for each object */
  		if (unreachable->gc_next == gc) {
! 			/* still alive, move it, it may die later */
  			gc_list_remove(gc);
  			gc_list_append(gc, old);
--- 336,351 ----
  		PyGC_Head *gc = unreachable->gc_next;
  		PyObject *op = PyObject_FROM_GC(gc);
! 		if (debug & DEBUG_SAVEALL) {
! 			PyList_Append(garbage, op);
  		}
! 		else {
! 			if ((clear = op->ob_type->tp_clear) != NULL) {
! 				Py_INCREF(op);
! 				clear((PyObject *)op);
! 				Py_DECREF(op);
! 			}
! 		}
  		if (unreachable->gc_next == gc) {
! 			/* object is still alive, move it, it may die later */
  			gc_list_remove(gc);
  			gc_list_append(gc, old);
***************
*** 426,430 ****
  		if (m == 0 && n == 0) {
  			PySys_WriteStderr("gc: done.\n");
! 		} else {
  			PySys_WriteStderr(
  			    "gc: done, %ld unreachable, %ld uncollectable.\n",
--- 432,437 ----
  		if (m == 0 && n == 0) {
  			PySys_WriteStderr("gc: done.\n");
! 		}
! 		else {
  			PySys_WriteStderr(
  			    "gc: done, %ld unreachable, %ld uncollectable.\n",
***************
*** 439,442 ****
--- 446,452 ----
  
  	if (PyErr_Occurred()) {
+ 		if (gc_str == NULL) {
+ 		    gc_str = PyString_FromString("garbage collection");
+ 		}
  		PyErr_WriteUnraisable(gc_str);
  		Py_FatalError("unexpected exception during garbage collection");
***************
*** 462,466 ****
  		}
  		collections1 = 0;
! 	} else if (collections0 > threshold1) {
  		generation = 1;
  		collections1++;
--- 472,477 ----
  		}
  		collections1 = 0;
! 	}
! 	else if (collections0 > threshold1) {
  		generation = 1;
  		collections1++;
***************
*** 470,474 ****
  		}
  		collections0 = 0;
! 	} else {
  		generation = 0;
  		collections0++;
--- 481,486 ----
  		}
  		collections0 = 0;
! 	}
! 	else {
  		generation = 0;
  		collections0++;
***************
*** 604,607 ****
--- 616,620 ----
  "  DEBUG_INSTANCES - Print instance objects.\n"
  "  DEBUG_OBJECTS - Print objects other than instances.\n"
+ "  DEBUG_SAVEALL - Save objects to gc.garbage rather than freeing them.\n"
  "  DEBUG_LEAK - Debug leaking programs (everything but STATS).\n"
  ;
***************
*** 680,685 ****
  
  static PyMethodDef GcMethods[] = {
! 	{"enable",	   gc_enable,     METH_VARARGS, gc_enable__doc__},
! 	{"disable",	   gc_disable,    METH_VARARGS, gc_disable__doc__},
  	{"isenabled",	   gc_isenabled,  METH_VARARGS, gc_isenabled__doc__},
  	{"set_debug",	   gc_set_debug,  METH_VARARGS, gc_set_debug__doc__},
--- 693,698 ----
  
  static PyMethodDef GcMethods[] = {
! 	{"enable",	   gc_enable,	  METH_VARARGS, gc_enable__doc__},
! 	{"disable",	   gc_disable,	  METH_VARARGS, gc_disable__doc__},
  	{"isenabled",	   gc_isenabled,  METH_VARARGS, gc_isenabled__doc__},
  	{"set_debug",	   gc_set_debug,  METH_VARARGS, gc_set_debug__doc__},
***************
*** 687,691 ****
  	{"set_threshold",  gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__},
  	{"get_threshold",  gc_get_thresh, METH_VARARGS, gc_get_thresh__doc__},
! 	{"collect",	   gc_collect,    METH_VARARGS, gc_collect__doc__},
  	{NULL,	NULL}		/* Sentinel */
  };
--- 700,704 ----
  	{"set_threshold",  gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__},
  	{"get_threshold",  gc_get_thresh, METH_VARARGS, gc_get_thresh__doc__},
! 	{"collect",	   gc_collect,	  METH_VARARGS, gc_collect__doc__},
  	{NULL,	NULL}		/* Sentinel */
  };
***************
*** 706,712 ****
  		garbage = PyList_New(0);
  	}
- 	if (gc_str == NULL) {
- 		gc_str = PyString_FromString("garbage collection");
- 	}
  	PyDict_SetItemString(d, "garbage", garbage);
  	PyDict_SetItemString(d, "DEBUG_STATS",
--- 719,722 ----
***************
*** 720,723 ****
--- 730,735 ----
  	PyDict_SetItemString(d, "DEBUG_OBJECTS",
  			PyInt_FromLong(DEBUG_OBJECTS));
+ 	PyDict_SetItemString(d, "DEBUG_SAVEALL",
+ 			PyInt_FromLong(DEBUG_SAVEALL));
  	PyDict_SetItemString(d, "DEBUG_LEAK",
  			PyInt_FromLong(DEBUG_LEAK));