summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2003-04-19 18:47:02 (GMT)
committerTim Peters <tim.peters@gmail.com>2003-04-19 18:47:02 (GMT)
commitcf615b52750f557d3c1d4fd8ba9142158e369acd (patch)
treeef8c527cdce494e7e0efe283e5b4c3f7670563b0
parent53f72d7dcd373106cad3b4dbe6b83d2be0fc4e12 (diff)
downloadcpython-cf615b52750f557d3c1d4fd8ba9142158e369acd.zip
cpython-cf615b52750f557d3c1d4fd8ba9142158e369acd.tar.gz
cpython-cf615b52750f557d3c1d4fd8ba9142158e369acd.tar.bz2
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.
-rw-r--r--Python/pythonrun.c20
1 files 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