mirror of https://github.com/python/cpython
Closes issue 15505. unittest.installHandler and non-callable signal handlers.
This commit is contained in:
parent
45c4375ea7
commit
6debd76939
|
@ -9,6 +9,20 @@ __unittest = True
|
|||
class _InterruptHandler(object):
|
||||
def __init__(self, default_handler):
|
||||
self.called = False
|
||||
self.original_handler = default_handler
|
||||
if isinstance(default_handler, int):
|
||||
if default_handler == signal.SIG_DFL:
|
||||
# Pretend it's signal.default_int_handler instead.
|
||||
default_handler = signal.default_int_handler
|
||||
elif default_handler == signal.SIG_IGN:
|
||||
# Not quite the same thing as SIG_IGN, but the closest we
|
||||
# can make it: do nothing.
|
||||
def default_handler(unused_signum, unused_frame):
|
||||
pass
|
||||
else:
|
||||
raise TypeError("expected SIGINT signal handler to be "
|
||||
"signal.SIG_IGN, signal.SIG_DFL, or a "
|
||||
"callable object")
|
||||
self.default_handler = default_handler
|
||||
|
||||
def __call__(self, signum, frame):
|
||||
|
@ -54,4 +68,4 @@ def removeHandler(method=None):
|
|||
|
||||
global _interrupt_handler
|
||||
if _interrupt_handler is not None:
|
||||
signal.signal(signal.SIGINT, _interrupt_handler.default_handler)
|
||||
signal.signal(signal.SIGINT, _interrupt_handler.original_handler)
|
||||
|
|
|
@ -13,9 +13,12 @@ import unittest
|
|||
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||
"if threads have been used")
|
||||
class TestBreak(unittest.TestCase):
|
||||
int_handler = None
|
||||
|
||||
def setUp(self):
|
||||
self._default_handler = signal.getsignal(signal.SIGINT)
|
||||
if self.int_handler is not None:
|
||||
signal.signal(signal.SIGINT, self.int_handler)
|
||||
|
||||
def tearDown(self):
|
||||
signal.signal(signal.SIGINT, self._default_handler)
|
||||
|
@ -72,6 +75,10 @@ class TestBreak(unittest.TestCase):
|
|||
|
||||
|
||||
def testSecondInterrupt(self):
|
||||
# Can't use skipIf decorator because the signal handler may have
|
||||
# been changed after defining this method.
|
||||
if signal.getsignal(signal.SIGINT) == signal.SIG_IGN:
|
||||
self.skipTest("test requires SIGINT to not be ignored")
|
||||
result = unittest.TestResult()
|
||||
unittest.installHandler()
|
||||
unittest.registerResult(result)
|
||||
|
@ -121,6 +128,10 @@ class TestBreak(unittest.TestCase):
|
|||
|
||||
|
||||
def testHandlerReplacedButCalled(self):
|
||||
# Can't use skipIf decorator because the signal handler may have
|
||||
# been changed after defining this method.
|
||||
if signal.getsignal(signal.SIGINT) == signal.SIG_IGN:
|
||||
self.skipTest("test requires SIGINT to not be ignored")
|
||||
# If our handler has been replaced (is no longer installed) but is
|
||||
# called by the *new* handler, then it isn't safe to delay the
|
||||
# SIGINT and we should immediately delegate to the default handler
|
||||
|
@ -250,3 +261,24 @@ class TestBreak(unittest.TestCase):
|
|||
|
||||
test()
|
||||
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
|
||||
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
|
||||
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||
"if threads have been used")
|
||||
class TestBreakDefaultIntHandler(TestBreak):
|
||||
int_handler = signal.default_int_handler
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
|
||||
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
|
||||
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||
"if threads have been used")
|
||||
class TestBreakSignalIgnored(TestBreak):
|
||||
int_handler = signal.SIG_IGN
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
|
||||
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
|
||||
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||
"if threads have been used")
|
||||
class TestBreakSignalDefault(TestBreak):
|
||||
int_handler = signal.SIG_DFL
|
||||
|
|
Loading…
Reference in New Issue