Issue #18776: atexit callbacks now display their full traceback when they raise an exception.
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 5200af7..30c3b4a 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -74,6 +74,25 @@
         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():
diff --git a/Misc/NEWS b/Misc/NEWS
index 32b9395..3b5b4c5 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -76,6 +76,9 @@
 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``.
 
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 9ef653b..ee277b6 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1880,6 +1880,16 @@
 {
     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 */
     }