refactor __del__ exception handler into PyErr_WriteUnraisable
add sanity check to gc: if an exception occurs during GC, call
PyErr_WriteUnraisable and then call Py_FatalEror.
diff --git a/Doc/api/api.tex b/Doc/api/api.tex
index 1f20129..c8731c9 100644
--- a/Doc/api/api.tex
+++ b/Doc/api/api.tex
@@ -972,6 +972,17 @@
 a dictionary of class variables and methods.
 \end{cfuncdesc}
 
+\begin{cfuncdesc}{void}{PyErr_WriteUnraisable}{PyObject *obj}
+This utility function prints a warning message to \var{sys.stderr}
+when an exception has been set but it is impossible for the
+interpreter to actually raise the exception.  It is used, for example,
+when an exception occurs in an \member{__del__} method.
+
+The function is called with a single argument \var{obj} that
+identifies where the context in which the unraisable exception
+occurred.  The repr of \var{obj} will be printed in the warning
+message.
+\end{cfuncdesc}
 
 \section{Standard Exceptions \label{standardExceptions}}
 
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 6e60353..311e258 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -92,6 +92,7 @@
 /* Function to create a new exception */
 DL_IMPORT(PyObject *) PyErr_NewException(char *name, PyObject *base,
                                          PyObject *dict);
+extern DL_IMPORT(void) PyErr_WriteUnraisable(PyObject *);
 
 /* In sigcheck.c or signalmodule.c */
 extern DL_IMPORT(int) PyErr_CheckSignals(void);
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 57ee7b9..889ae25 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -57,11 +57,13 @@
 				DEBUG_UNCOLLECTABLE | \
 				DEBUG_INSTANCES | \
 				DEBUG_OBJECTS
-static int debug = 0;
+static int debug;
 
 /* list of uncollectable objects */
 static PyObject *garbage;
 
+/* Python string to use if unhandled exception occurs */
+static PyObject *gc_str;
 
 /*** list functions ***/
 
@@ -435,6 +437,10 @@
 	 * this if they insist on creating this type of structure. */
 	handle_finalizers(&finalizers, old);
 
+	if (PyErr_Occurred()) {
+		PyErr_WriteUnraisable(gc_str);
+		Py_FatalError("unexpected exception during garbage collection");
+	}
 	allocated = 0;
 	return n+m;
 }
@@ -699,6 +705,9 @@
 	if (garbage == NULL) {
 		garbage = PyList_New(0);
 	}
+	if (gc_str == NULL) {
+		gc_str = PyString_FromString("garbage collection");
+	}
 	PyDict_SetItemString(d, "garbage", garbage);
 	PyDict_SetItemString(d, "DEBUG_STATS",
 			PyInt_FromLong(DEBUG_STATS));
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 0b595b9..615c8ba 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -519,26 +519,7 @@
 	if ((del = instance_getattr2(inst, delstr)) != NULL) {
 		PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);
 		if (res == NULL) {
-			PyObject *f, *t, *v, *tb;
- 			PyErr_Fetch(&t, &v, &tb);
-			f = PySys_GetObject("stderr");
-			if (f != NULL) {
-				PyFile_WriteString("Exception ", f);
-				if (t) {
-					PyFile_WriteObject(t, f, Py_PRINT_RAW);
-					if (v && v != Py_None) {
-						PyFile_WriteString(": ", f);
-						PyFile_WriteObject(v, f, 0);
-					}
-				}
-				PyFile_WriteString(" in ", f);
-				PyFile_WriteObject(del, f, 0);
-				PyFile_WriteString(" ignored\n", f);
-				PyErr_Clear(); /* Just in case */
-			}
-			Py_XDECREF(t);
-			Py_XDECREF(v);
-			Py_XDECREF(tb);
+			PyErr_WriteUnraisable(del);
 		}
 		else
 			Py_DECREF(res);
diff --git a/Python/errors.c b/Python/errors.c
index 8486423..355ec9c 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -450,3 +450,30 @@
 	Py_XDECREF(modulename);
 	return result;
 }
+
+/* Call when an exception has occurred but there is no way for Python
+   to handle it.  Examples: exception in __del__ or during GC. */
+void
+PyErr_WriteUnraisable(PyObject *obj)
+{
+	PyObject *f, *t, *v, *tb;
+	PyErr_Fetch(&t, &v, &tb);
+	f = PySys_GetObject("stderr");
+	if (f != NULL) {
+		PyFile_WriteString("Exception ", f);
+		if (t) {
+			PyFile_WriteObject(t, f, Py_PRINT_RAW);
+			if (v && v != Py_None) {
+				PyFile_WriteString(": ", f);
+				PyFile_WriteObject(v, f, 0);
+			}
+		}
+		PyFile_WriteString(" in ", f);
+		PyFile_WriteObject(obj, f, 0);
+		PyFile_WriteString(" ignored\n", f);
+		PyErr_Clear(); /* Just in case */
+	}
+	Py_XDECREF(t);
+	Py_XDECREF(v);
+	Py_XDECREF(tb);
+}