summaryrefslogtreecommitdiffstats
path: root/Python/pythonrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pythonrun.c')
-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