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.
This commit is contained in:
Victor Stinner 2011-05-25 02:35:58 +02:00
parent b45c7087aa
commit c13ef66649
2 changed files with 37 additions and 8 deletions

View file

@ -226,10 +226,16 @@ class WakeupSignalTests(unittest.TestCase):
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 @@ class WakeupSignalTests(unittest.TestCase):
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

View file

@ -177,17 +177,18 @@ static void
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