summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-05-03 12:57:12 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2011-05-03 12:57:12 (GMT)
commitd0e516db50376ab0fd729c42bafda3e5a6225b94 (patch)
tree125054b4762cd8c0bed63d1a4b82c135f8d5275f
parent2d4a91e0d0065b89cb9820b10e30f74c362cb430 (diff)
downloadcpython-d0e516db50376ab0fd729c42bafda3e5a6225b94.zip
cpython-d0e516db50376ab0fd729c42bafda3e5a6225b94.tar.gz
cpython-d0e516db50376ab0fd729c42bafda3e5a6225b94.tar.bz2
Issue #8407: pthread_sigmask() checks immediatly if signal handlers have been
called. The test checks that SIG_UNBLOCK calls immediatly the signal handler of the pending SIGUSR1. Improve also the tests using an exception (division by zero) instead of a flag (a function attribute).
-rw-r--r--Lib/test/test_signal.py30
-rw-r--r--Modules/signalmodule.c4
2 files changed, 20 insertions, 14 deletions
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index 5caf13d..1a28ced 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -498,8 +498,7 @@ class PthreadSigmaskTests(unittest.TestCase):
signum = signal.SIGUSR1
def handler(signum, frame):
- handler.tripped = True
- handler.tripped = False
+ 1/0
def read_sigmask():
return signal.pthread_sigmask(signal.SIG_BLOCK, [])
@@ -519,36 +518,39 @@ class PthreadSigmaskTests(unittest.TestCase):
# function.
faulthandler.cancel_dump_tracebacks_later()
+ # Install our signal handler
old_handler = signal.signal(signum, handler)
self.addCleanup(signal.signal, signum, old_handler)
- # unblock SIGUSR1, copy the old mask and test our signal handler
+ # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask)
- os.kill(pid, signum)
- self.assertTrue(handler.tripped)
+ with self.assertRaises(ZeroDivisionError):
+ os.kill(pid, signum)
- # block SIGUSR1
- handler.tripped = False
+ # Block and then raise SIGUSR1. The signal is blocked: the signal
+ # handler is not called, and the signal is now pending
signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
os.kill(pid, signum)
- self.assertFalse(handler.tripped)
- # check the mask
+ # Check the new mask
blocked = read_sigmask()
self.assertIn(signum, blocked)
self.assertEqual(set(old_mask) ^ set(blocked), {signum})
- # unblock SIGUSR1
- signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
- os.kill(pid, signum)
- self.assertTrue(handler.tripped)
+ # Unblock SIGUSR1
+ with self.assertRaises(ZeroDivisionError):
+ # unblock the pending signal calls immediatly the signal handler
+ signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
+ with self.assertRaises(ZeroDivisionError):
+ os.kill(pid, signum)
- # check the mask
+ # Check the new mask
unblocked = read_sigmask()
self.assertNotIn(signum, unblocked)
self.assertEqual(set(blocked) ^ set(unblocked), {signum})
self.assertSequenceEqual(old_mask, unblocked)
+ # Finally, restore the previous signal handler and the signal mask
def test_main():
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 0cb2720..387dc8c 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -573,6 +573,10 @@ signal_pthread_sigmask(PyObject *self, PyObject *args)
return NULL;
}
+ /* if signals was unblocked, signal handlers have been called */
+ if (PyErr_CheckSignals())
+ return NULL;
+
result = PyList_New(0);
if (result == NULL)
return NULL;