[Python-checkins] cpython: Issue #8407: Fix the signal handler of the signal module: if it is called

victor.stinner python-checkins at python.org
Wed May 25 02:38:28 CEST 2011


http://hg.python.org/cpython/rev/234021dcad93
changeset:   70368:234021dcad93
user:        Victor Stinner <victor.stinner at haypocalc.com>
date:        Wed May 25 02:35:58 2011 +0200
summary:
  Issue #8407: Fix the signal handler of the signal module: if it is called
twice, it now writes the number of the second signal into the wakeup fd.

files:
  Lib/test/test_signal.py |  36 +++++++++++++++++++++++++---
  Modules/signalmodule.c  |   9 ++++---
  2 files changed, 37 insertions(+), 8 deletions(-)


diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -226,10 +226,16 @@
     TIMEOUT_FULL = 10
     TIMEOUT_HALF = 5
 
-    def check_signum(self, *signals):
+    def handler(self, signum, frame):
+        pass
+
+    def check_signum(self, *signals, **kw):
         data = os.read(self.read, len(signals)+1)
         raised = struct.unpack('%uB' % len(data), data)
-        self.assertSequenceEqual(raised, signals)
+        if kw.get('unordered', False):
+            raised = set(raised)
+            signals = set(signals)
+        self.assertEqual(raised, signals)
 
     def test_wakeup_fd_early(self):
         import select
@@ -259,16 +265,38 @@
         self.check_signum(signal.SIGALRM)
 
     def test_signum(self):
-        old_handler = signal.signal(signal.SIGUSR1, lambda x,y:None)
+        old_handler = signal.signal(signal.SIGUSR1, self.handler)
         self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)
         os.kill(os.getpid(), signal.SIGUSR1)
         os.kill(os.getpid(), signal.SIGALRM)
         self.check_signum(signal.SIGUSR1, signal.SIGALRM)
 
+    @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
+                         'need signal.pthread_sigmask()')
+    @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
+                         'need signal.pthread_kill()')
+    def test_pending(self):
+        signum1 = signal.SIGUSR1
+        signum2 = signal.SIGUSR2
+        tid = threading.current_thread().ident
+
+        old_handler = signal.signal(signum1, self.handler)
+        self.addCleanup(signal.signal, signum1, old_handler)
+        old_handler = signal.signal(signum2, self.handler)
+        self.addCleanup(signal.signal, signum2, old_handler)
+
+        signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
+        signal.pthread_kill(tid, signum1)
+        signal.pthread_kill(tid, signum2)
+        # Unblocking the 2 signals calls the C signal handler twice
+        signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
+
+        self.check_signum(signum1, signum2, unordered=True)
+
     def setUp(self):
         import fcntl
 
-        self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
+        self.alrm = signal.signal(signal.SIGALRM, self.handler)
         self.read, self.write = os.pipe()
         flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
         flags = flags | os.O_NONBLOCK
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -177,17 +177,18 @@
 trip_signal(int sig_num)
 {
     unsigned char byte;
+
     Handlers[sig_num].tripped = 1;
+    if (wakeup_fd != -1) {
+        byte = (unsigned char)sig_num;
+        write(wakeup_fd, &byte, 1);
+    }
     if (is_tripped)
         return;
     /* Set is_tripped after setting .tripped, as it gets
        cleared in PyErr_CheckSignals() before .tripped. */
     is_tripped = 1;
     Py_AddPendingCall(checksignals_witharg, NULL);
-    if (wakeup_fd != -1) {
-        byte = (unsigned char)sig_num;
-        write(wakeup_fd, &byte, 1);
-    }
 }
 
 static void

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list