]> granicus.if.org Git - python/commitdiff
Issue #18776: atexit callbacks now display their full traceback when they raise an...
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 13 Oct 2013 19:53:13 +0000 (21:53 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 13 Oct 2013 19:53:13 +0000 (21:53 +0200)
Lib/test/test_atexit.py
Misc/NEWS
Python/pythonrun.c

index 5200af7ed91a6a1e4521651fdfa7928e8652239a..30c3b4a07b822b34c68f766f868f0c1a1096f9de 100644 (file)
@@ -74,6 +74,25 @@ class TestCase(unittest.TestCase):
         self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
         self.assertIn("ZeroDivisionError", self.stream.getvalue())
 
+    def test_print_tracebacks(self):
+        # Issue #18776: the tracebacks should be printed when errors occur.
+        def f():
+            1/0  # one
+        def g():
+            1/0  # two
+        def h():
+            1/0  # three
+        atexit.register(f)
+        atexit.register(g)
+        atexit.register(h)
+
+        self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
+        stderr = self.stream.getvalue()
+        self.assertEqual(stderr.count("ZeroDivisionError"), 3)
+        self.assertIn("# one", stderr)
+        self.assertIn("# two", stderr)
+        self.assertIn("# three", stderr)
+
     def test_stress(self):
         a = [0]
         def inc():
index 32b9395f25acd2df46df2bcd43ae2a83ed48be52..3b5b4c50340557ab16139c1fb9089d2efceedee4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -76,6 +76,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #18776: atexit callbacks now display their full traceback when they
+  raise an exception.
+
 - Issue #17827: Add the missing documentation for ``codecs.encode`` and
   ``codecs.decode``.
 
index 9ef653b57a827a47f5c729e1cfe4c295b2f7fbaf..ee277b67f2cf31e24a457e9c7b689363abe07fa5 100644 (file)
@@ -1880,6 +1880,16 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
 {
     PyObject *seen;
     PyObject *f = PySys_GetObject("stderr");
+    if (PyExceptionInstance_Check(value)
+        && tb != NULL && PyTraceBack_Check(tb)) {
+        /* Put the traceback on the exception, otherwise it won't get
+           displayed.  See issue #18776. */
+        PyObject *cur_tb = PyException_GetTraceback(value);
+        if (cur_tb == NULL)
+            PyException_SetTraceback(value, tb);
+        else
+            Py_DECREF(cur_tb);
+    }
     if (f == Py_None) {
         /* pass */
     }