From cf615b52750f557d3c1d4fd8ba9142158e369acd Mon Sep 17 00:00:00 2001
From: Tim Peters <tim.peters@gmail.com>
Date: Sat, 19 Apr 2003 18:47:02 +0000
Subject: handle_system_exit():  This leaked the current exception info, in
 particular leaving the traceback object (and everything reachable from it)
 alive throughout shutdown.  The patch is mostly from Guido.

Bugfix candidate.
---
 Python/pythonrun.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 29ba120..e5759b7 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -914,12 +914,14 @@ static void
 handle_system_exit(void)
 {
         PyObject *exception, *value, *tb;
+        int exitcode = 0;
+
 	PyErr_Fetch(&exception, &value, &tb);
 	if (Py_FlushLine())
 		PyErr_Clear();
 	fflush(stdout);
 	if (value == NULL || value == Py_None)
-		Py_Exit(0);
+		goto done;
 	if (PyInstance_Check(value)) {
 		/* The error code should be in the `code' attribute. */
 		PyObject *code = PyObject_GetAttrString(value, "code");
@@ -927,18 +929,28 @@ handle_system_exit(void)
 			Py_DECREF(value);
 			value = code;
 			if (value == Py_None)
-				Py_Exit(0);
+				goto done;
 		}
 		/* If we failed to dig out the 'code' attribute,
 		   just let the else clause below print the error. */
 	}
 	if (PyInt_Check(value))
-		Py_Exit((int)PyInt_AsLong(value));
+		exitcode = (int)PyInt_AsLong(value);
 	else {
 		PyObject_Print(value, stderr, Py_PRINT_RAW);
 		PySys_WriteStderr("\n");
-		Py_Exit(1);
+		exitcode = 1;
 	}
+ done:
+ 	/* Restore and clear the exception info, in order to properly decref
+ 	 * the exception, value, and traceback.  If we just exit instead,
+ 	 * these leak, which confuses PYTHONDUMPREFS output, and may prevent
+ 	 * some finalizers from running.
+ 	 */
+	PyErr_Restore(exception, value, tb);
+	PyErr_Clear();
+	Py_Exit(exitcode);
+	/* NOTREACHED */
 }
 
 void
-- 
cgit v0.12

