[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));