Christian Tismer's "trashcan" patch:

Added wrapping macros to dictobject.c, listobject.c, tupleobject.c,
frameobject.c, traceback.c that safely prevends core dumps
on stack overflow. Macros and functions in object.c, object.h.
The method is an "elevator destructor" that turns cascading
deletes into tail recursive behavior when some limit is hit.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index ceec39d..ea32e23 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -479,6 +479,7 @@
 {
 	register int i;
 	register dictentry *ep;
+	Py_TRASHCAN_SAFE_BEGIN(mp)
 	for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
 		if (ep->me_key != NULL) {
 			Py_DECREF(ep->me_key);
@@ -489,6 +490,7 @@
 	}
 	PyMem_XDEL(mp->ma_table);
 	PyMem_DEL(mp);
+	Py_TRASHCAN_SAFE_END(mp)
 }
 
 static int
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index dcd760c..4c716cd 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -103,6 +103,7 @@
 	int i;
 	PyObject **fastlocals;
 
+	Py_TRASHCAN_SAFE_BEGIN(f)
 	/* Kill all local variables */
 	fastlocals = f->f_localsplus;
 	for (i = f->f_nlocals; --i >= 0; ++fastlocals) {
@@ -120,6 +121,7 @@
 	Py_XDECREF(f->f_exc_traceback);
 	f->f_back = free_list;
 	free_list = f;
+	Py_TRASHCAN_SAFE_END(f)
 }
 
 PyTypeObject PyFrame_Type = {
diff --git a/Objects/listobject.c b/Objects/listobject.c
index d77b546..673028f 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -215,6 +215,7 @@
 	PyListObject *op;
 {
 	int i;
+	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (op->ob_item != NULL) {
 		/* Do it backwards, for Christian Tismer.
 		   There's a simple test case where somehow this reduces
@@ -227,6 +228,7 @@
 		free((ANY *)op->ob_item);
 	}
 	free((ANY *)op);
+	Py_TRASHCAN_SAFE_END(op)
 }
 
 static int
diff --git a/Objects/object.c b/Objects/object.c
index 7a41aa2..d2aa542 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -906,3 +906,48 @@
 		}
 	}
 }
+
+/*
+  trashcan
+  CT 2k0130
+  non-recursively destroy nested objects
+
+  CT 2k0223
+  everything is now done in a macro.
+
+  CT 2k0305
+  modified to use functions, after Tim Peter's suggestion.
+
+  CT 2k0309
+  modified to restore a possible error.
+*/
+
+int _PyTrash_delete_nesting = 0;
+PyObject * _PyTrash_delete_later = NULL;
+
+void
+_PyTrash_deposit_object(op)
+	PyObject *op;
+{
+	PyObject *error_type, *error_value, *error_traceback;
+	PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+	if (!_PyTrash_delete_later)
+		_PyTrash_delete_later = PyList_New(0);
+	if (_PyTrash_delete_later)
+		PyList_Append(_PyTrash_delete_later, (PyObject *)op);
+
+	PyErr_Restore(error_type, error_value, error_traceback);
+}
+
+void
+_PyTrash_destroy_list()
+{
+	while (_PyTrash_delete_later) {
+		PyObject *shredder = _PyTrash_delete_later;
+		_PyTrash_delete_later = NULL;
+		++_PyTrash_delete_nesting;
+		Py_DECREF(shredder);
+		--_PyTrash_delete_nesting;
+	}
+}
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 568c4b3..5112468 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -172,6 +172,7 @@
 {
 	register int i;
 
+	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (op->ob_size > 0) {
 		i = op->ob_size;
 		while (--i >= 0)
@@ -180,11 +181,13 @@
 		if (op->ob_size < MAXSAVESIZE) {
 			op->ob_item[0] = (PyObject *) free_tuples[op->ob_size];
 			free_tuples[op->ob_size] = op;
-			return;
+			goto done; /* return */
 		}
 #endif
 	}
 	free((ANY *)op);
+done:
+	Py_TRASHCAN_SAFE_END(op)
 }
 
 static int