blob: 2f7eb607c7e7c143bcccc444b2ac1b05efb1cd70 [file] [log] [blame]
Michael W. Hudson43220ea2004-08-03 14:37:14 +00001"""PyUnit testing that threads honor our signal semantics"""
2
3import unittest
Michael W. Hudson43220ea2004-08-03 14:37:14 +00004import signal
5import os
Fred Drake48187482004-08-03 16:14:13 +00006import sys
Florent Xiclunad6722292010-07-27 22:48:26 +00007from test.test_support import run_unittest, import_module, reap_threads
Victor Stinner6a102812010-04-27 23:55:59 +00008thread = import_module('thread')
Michael W. Hudson43220ea2004-08-03 14:37:14 +00009
Michael W. Hudson34fba3b2004-08-03 15:35:29 +000010if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos':
Benjamin Petersonbec087f2009-03-26 21:10:30 +000011 raise unittest.SkipTest, "Can't test signal on %s" % sys.platform
Michael W. Hudson34fba3b2004-08-03 15:35:29 +000012
Michael W. Hudson43220ea2004-08-03 14:37:14 +000013process_pid = os.getpid()
14signalled_all=thread.allocate_lock()
15
16
Ezio Melottidde5b942010-02-03 05:37:26 +000017def registerSignals(for_usr1, for_usr2, for_alrm):
Michael W. Hudson43220ea2004-08-03 14:37:14 +000018 usr1 = signal.signal(signal.SIGUSR1, for_usr1)
19 usr2 = signal.signal(signal.SIGUSR2, for_usr2)
20 alrm = signal.signal(signal.SIGALRM, for_alrm)
21 return usr1, usr2, alrm
22
23
Fred Drakedb390c12005-10-28 14:39:47 +000024# The signal handler. Just note that the signal occurred and
Michael W. Hudson43220ea2004-08-03 14:37:14 +000025# from who.
26def handle_signals(sig,frame):
Tim Peters6db15d72004-08-04 02:36:18 +000027 signal_blackboard[sig]['tripped'] += 1
Michael W. Hudson43220ea2004-08-03 14:37:14 +000028 signal_blackboard[sig]['tripped_by'] = thread.get_ident()
29
30# a function that will be spawned as a separate thread.
31def send_signals():
32 os.kill(process_pid, signal.SIGUSR1)
33 os.kill(process_pid, signal.SIGUSR2)
34 signalled_all.release()
35
36class ThreadSignals(unittest.TestCase):
37 """Test signal handling semantics of threads.
38 We spawn a thread, have the thread send two signals, and
39 wait for it to finish. Check that we got both signals
40 and that they were run by the main thread.
41 """
Florent Xiclunad6722292010-07-27 22:48:26 +000042 @reap_threads
Michael W. Hudson43220ea2004-08-03 14:37:14 +000043 def test_signals(self):
44 signalled_all.acquire()
45 self.spawnSignallingThread()
46 signalled_all.acquire()
47 # the signals that we asked the kernel to send
48 # will come back, but we don't know when.
49 # (it might even be after the thread exits
50 # and might be out of order.) If we haven't seen
51 # the signals yet, send yet another signal and
52 # wait for it return.
Tim Peters1742f332006-08-12 04:42:47 +000053 if signal_blackboard[signal.SIGUSR1]['tripped'] == 0 \
Michael W. Hudson43220ea2004-08-03 14:37:14 +000054 or signal_blackboard[signal.SIGUSR2]['tripped'] == 0:
Tim Peters6db15d72004-08-04 02:36:18 +000055 signal.alarm(1)
56 signal.pause()
57 signal.alarm(0)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000058
59 self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped'], 1)
Tim Peters6db15d72004-08-04 02:36:18 +000060 self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped_by'],
Michael W. Hudson43220ea2004-08-03 14:37:14 +000061 thread.get_ident())
62 self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped'], 1)
Tim Peters6db15d72004-08-04 02:36:18 +000063 self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped_by'],
Michael W. Hudson43220ea2004-08-03 14:37:14 +000064 thread.get_ident())
Michael W. Hudson574a2512004-08-04 14:22:56 +000065 signalled_all.release()
Michael W. Hudson43220ea2004-08-03 14:37:14 +000066
67 def spawnSignallingThread(self):
68 thread.start_new_thread(send_signals, ())
Tim Peters6db15d72004-08-04 02:36:18 +000069
Michael W. Hudson43220ea2004-08-03 14:37:14 +000070
71def test_main():
Michael W. Hudson574a2512004-08-04 14:22:56 +000072 global signal_blackboard
Tim Petersd1b78272004-08-07 06:03:09 +000073
Michael W. Hudson574a2512004-08-04 14:22:56 +000074 signal_blackboard = { signal.SIGUSR1 : {'tripped': 0, 'tripped_by': 0 },
75 signal.SIGUSR2 : {'tripped': 0, 'tripped_by': 0 },
76 signal.SIGALRM : {'tripped': 0, 'tripped_by': 0 } }
77
Ezio Melottidde5b942010-02-03 05:37:26 +000078 oldsigs = registerSignals(handle_signals, handle_signals, handle_signals)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000079 try:
Michael W. Hudson574a2512004-08-04 14:22:56 +000080 run_unittest(ThreadSignals)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000081 finally:
Ezio Melottidde5b942010-02-03 05:37:26 +000082 registerSignals(*oldsigs)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000083
84if __name__ == '__main__':
85 test_main()