blob: 1c32dfda5166b7c50f3798647f191313b45d1f74 [file] [log] [blame]
Michael W. Hudson43220ea2004-08-03 14:37:14 +00001"""PyUnit testing that threads honor our signal semantics"""
2
3import unittest
4import thread
5import signal
6import os
7from test import test_support
8
Michael W. Hudson34fba3b2004-08-03 15:35:29 +00009if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos':
10 raise TestSkipped, "Can't test signal on %s" % sys.platform
11
Michael W. Hudson43220ea2004-08-03 14:37:14 +000012signal_blackboard = { signal.SIGUSR1 : {'tripped': 0, 'tripped_by': 0 },
13 signal.SIGUSR2 : {'tripped': 0, 'tripped_by': 0 },
14 signal.SIGALRM : {'tripped': 0, 'tripped_by': 0 } }
15
16process_pid = os.getpid()
17signalled_all=thread.allocate_lock()
18
19
20def registerSignals((for_usr1, for_usr2, for_alrm)):
21 usr1 = signal.signal(signal.SIGUSR1, for_usr1)
22 usr2 = signal.signal(signal.SIGUSR2, for_usr2)
23 alrm = signal.signal(signal.SIGALRM, for_alrm)
24 return usr1, usr2, alrm
25
26
27# The signal handler. Just note that the signal occured and
28# from who.
29def handle_signals(sig,frame):
30 signal_blackboard[sig]['tripped'] += 1
31 signal_blackboard[sig]['tripped_by'] = thread.get_ident()
32
33# a function that will be spawned as a separate thread.
34def send_signals():
35 os.kill(process_pid, signal.SIGUSR1)
36 os.kill(process_pid, signal.SIGUSR2)
37 signalled_all.release()
38
39class ThreadSignals(unittest.TestCase):
40 """Test signal handling semantics of threads.
41 We spawn a thread, have the thread send two signals, and
42 wait for it to finish. Check that we got both signals
43 and that they were run by the main thread.
44 """
45 def test_signals(self):
46 signalled_all.acquire()
47 self.spawnSignallingThread()
48 signalled_all.acquire()
49 # the signals that we asked the kernel to send
50 # will come back, but we don't know when.
51 # (it might even be after the thread exits
52 # and might be out of order.) If we haven't seen
53 # the signals yet, send yet another signal and
54 # wait for it return.
55 if signal_blackboard[signal.SIGUSR2]['tripped'] == 0 \
56 or signal_blackboard[signal.SIGUSR2]['tripped'] == 0:
57 signal.alarm(1)
58 signal.pause()
59 signal.alarm(0)
60
61 self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped'], 1)
62 self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped_by'],
63 thread.get_ident())
64 self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped'], 1)
65 self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped_by'],
66 thread.get_ident())
67
68 def spawnSignallingThread(self):
69 thread.start_new_thread(send_signals, ())
70
71
72def test_main():
73 oldsigs = registerSignals((handle_signals, handle_signals, handle_signals))
74 try:
75 test_support.run_unittest(ThreadSignals)
76 finally:
77 registerSignals(oldsigs)
78
79if __name__ == '__main__':
80 test_main()