diff options
author | Tim Peters <tim.peters@gmail.com> | 2003-04-19 18:47:02 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2003-04-19 18:47:02 (GMT) |
commit | cf615b52750f557d3c1d4fd8ba9142158e369acd (patch) | |
tree | ef8c527cdce494e7e0efe283e5b4c3f7670563b0 | |
parent | 53f72d7dcd373106cad3b4dbe6b83d2be0fc4e12 (diff) | |
download | cpython-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.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 |