Fix bug 1052242.  Also includes rewrite of test case using unittest and
avoiding use of popen.
diff --git a/Doc/lib/libatexit.tex b/Doc/lib/libatexit.tex
index c9775d1..922f5d4 100644
--- a/Doc/lib/libatexit.tex
+++ b/Doc/lib/libatexit.tex
@@ -39,6 +39,12 @@
 order.  The assumption is that lower level modules will normally be
 imported before higher level modules and thus must be cleaned up
 later.
+
+If an exception is raised during execution of the exit handlers, a traceback
+is printed (unless SystemExit is raised) and the exception information is
+saved.  After all exit handlers have had a chance to run the last exception
+to be raised is reraised.
+
 \end{funcdesc}
 
 
diff --git a/Lib/atexit.py b/Lib/atexit.py
index 85ccb24..e109eb5 100644
--- a/Lib/atexit.py
+++ b/Lib/atexit.py
@@ -15,9 +15,22 @@
     last in, first out.
     """
 
+    exc_info = None
     while _exithandlers:
         func, targs, kargs = _exithandlers.pop()
-        func(*targs, **kargs)
+        try:
+            func(*targs, **kargs)
+        except SystemExit:
+            exc_info = sys.exc_info()
+        except:
+            import sys, traceback
+            print >> sys.stderr, "Error in atexit._run_exitfuncs:"
+            traceback.print_exc()
+            exc_info = sys.exc_info()
+
+    if exc_info is not None:
+        raise exc_info[0], exc_info[1], exc_info[2]
+
 
 def register(func, *targs, **kargs):
     """register a function to be executed upon normal program termination
@@ -33,7 +46,6 @@
     # Assume it's another registered exit function - append it to our list
     register(sys.exitfunc)
 sys.exitfunc = _run_exitfuncs
-
 del sys
 
 if __name__ == "__main__":
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 1d120df..e57c48a 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -1,66 +1,100 @@
-# Test the atexit module.
-from test.test_support import TESTFN, vereq, is_jython
-import atexit
-from os import popen, unlink
 import sys
-
-executable = sys.executable
-if is_jython:
-    executable = "jython"
-
-input = """\
+import unittest
+import StringIO
 import atexit
+from test import test_support
 
-def handler1():
-    print "handler1"
+class TestCase(unittest.TestCase):
+    def test_args(self):
+        # be sure args are handled properly
+        s = StringIO.StringIO()
+        sys.stdout = sys.stderr = s
+        save_handlers = atexit._exithandlers
+        atexit._exithandlers = []
+        try:
+            atexit.register(self.h1)
+            atexit.register(self.h4)
+            atexit.register(self.h4, 4, kw="abc")
+            atexit._run_exitfuncs()
+        finally:
+            sys.stdout = sys.__stdout__
+            sys.stderr = sys.__stderr__
+            atexit._exithandlers = save_handlers
+        self.assertEqual(s.getvalue(), "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n")
 
-def handler2(*args, **kargs):
-    print "handler2", args, kargs
+    def test_order(self):
+        # be sure handlers are executed in reverse order
+        s = StringIO.StringIO()
+        sys.stdout = sys.stderr = s
+        save_handlers = atexit._exithandlers
+        atexit._exithandlers = []
+        try:
+            atexit.register(self.h1)
+            atexit.register(self.h2)
+            atexit.register(self.h3)
+            atexit._run_exitfuncs()
+        finally:
+            sys.stdout = sys.__stdout__
+            sys.stderr = sys.__stderr__
+            atexit._exithandlers = save_handlers
+        self.assertEqual(s.getvalue(), "h3\nh2\nh1\n")
 
-atexit.register(handler1)
-atexit.register(handler2)
-atexit.register(handler2, 7, kw="abc")
-"""
+    def test_sys_override(self):
+        # be sure a preset sys.exitfunc is handled properly
+        s = StringIO.StringIO()
+        sys.stdout = sys.stderr = s
+        save_handlers = atexit._exithandlers
+        atexit._exithandlers = []
+        exfunc = sys.exitfunc
+        sys.exitfunc = self.h1
+        reload(atexit)
+        try:
+            atexit.register(self.h2)
+            atexit._run_exitfuncs()
+        finally:
+            sys.stdout = sys.__stdout__
+            sys.stderr = sys.__stderr__
+            atexit._exithandlers = save_handlers
+            sys.exitfunc = exfunc
+        self.assertEqual(s.getvalue(), "h2\nh1\n")
 
-fname = TESTFN + ".py"
-f = file(fname, "w")
-f.write(input)
-f.close()
+    def test_raise(self):
+        # be sure raises are handled properly
+        s = StringIO.StringIO()
+        sys.stdout = sys.stderr = s
+        save_handlers = atexit._exithandlers
+        atexit._exithandlers = []
+        try:
+            atexit.register(self.raise1)
+            atexit.register(self.raise2)
+            self.assertRaises(TypeError, atexit._run_exitfuncs)
+        finally:
+            sys.stdout = sys.__stdout__
+            sys.stderr = sys.__stderr__
+            atexit._exithandlers = save_handlers
+       
+    ### helpers
+    def h1(self):
+        print "h1"
 
-p = popen('"%s" %s' % (executable, fname))
-output = p.read()
-p.close()
-vereq(output, """\
-handler2 (7,) {'kw': 'abc'}
-handler2 () {}
-handler1
-""")
+    def h2(self):
+        print "h2"
 
-input = """\
-def direct():
-    print "direct exit"
+    def h3(self):
+        print "h3"
 
-import sys
-sys.exitfunc = direct
+    def h4(self, *args, **kwargs):
+        print "h4", args, kwargs
 
-# Make sure atexit doesn't drop
-def indirect():
-    print "indirect exit"
+    def raise1(self):
+        raise TypeError
 
-import atexit
-atexit.register(indirect)
-"""
+    def raise2(self):
+        raise SystemError
 
-f = file(fname, "w")
-f.write(input)
-f.close()
+def test_main():
+    test_support.run_unittest(TestCase)
 
-p = popen('"%s" %s' % (executable, fname))
-output = p.read()
-p.close()
-vereq(output, """\
-indirect exit
-direct exit
-""")
 
-unlink(fname)
+if __name__ == "__main__":
+    test_main()
diff --git a/Misc/NEWS b/Misc/NEWS
index e2b1937..f44e10d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,17 @@
 Python News
 +++++++++++
 
+What's New in Python 2.4 release candidate 1?
+=============================================
+
+Library
+-------
+
+- Bug 1052242: If exceptions are raised by an atexit handler function an
+  attempt is made to execute the remaining handlers.  The last exception
+  raised is re-raised.
+
+
 (editors: check NEWS.help for information about editing NEWS using ReST.)
 
 What's New in Python 2.4 beta 2?