]> granicus.if.org Git - python/commitdiff
handle_system_exit(): This leaked the current exception info, in
authorTim Peters <tim.peters@gmail.com>
Sat, 19 Apr 2003 18:47:02 +0000 (18:47 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 19 Apr 2003 18:47:02 +0000 (18:47 +0000)
particular leaving the traceback object (and everything reachable
from it) alive throughout shutdown.  The patch is mostly from Guido.

Bugfix candidate.

Python/pythonrun.c

index 29ba120c2b7c85739173f2e2c54f0a7d1c1afd39..e5759b7eece9942c42ea1e8d44fcb69ea9581587 100644 (file)
@@ -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