diff options
-rw-r--r-- | Python/pythonrun.c | 20 |
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 |