summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSkip Montanaro <skip@pobox.com>2004-11-04 04:31:30 (GMT)
committerSkip Montanaro <skip@pobox.com>2004-11-04 04:31:30 (GMT)
commit599bd5e1e16aaa3a7652d245b6b2a018e772a557 (patch)
tree0c2437879be035ea36812826af8cb6565ee2045f /Lib
parented306292d68fe8ca3fb48f31129fe68229741519 (diff)
downloadcpython-599bd5e1e16aaa3a7652d245b6b2a018e772a557.zip
cpython-599bd5e1e16aaa3a7652d245b6b2a018e772a557.tar.gz
cpython-599bd5e1e16aaa3a7652d245b6b2a018e772a557.tar.bz2
Fix bug 1052242. Also includes rewrite of test case using unittest and
avoiding use of popen.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/atexit.py16
-rw-r--r--Lib/test/test_atexit.py138
2 files changed, 100 insertions, 54 deletions
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 @@ def _run_exitfuncs():
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 @@ if hasattr(sys, "exitfunc"):
# 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()