blob: 3d79fd508ef55fb26379b94e7729217fec447a2b [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:
Victor Stinner3604b232018-06-01 15:23:02 +020055 try:
56 signal.alarm(1)
57 signal.pause()
58 finally:
59 signal.alarm(0)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000060
61 self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped'], 1)
Tim Peters6db15d72004-08-04 02:36:18 +000062 self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped_by'],
Michael W. Hudson43220ea2004-08-03 14:37:14 +000063 thread.get_ident())
64 self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped'], 1)
Tim Peters6db15d72004-08-04 02:36:18 +000065 self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped_by'],
Michael W. Hudson43220ea2004-08-03 14:37:14 +000066 thread.get_ident())
Michael W. Hudson574a2512004-08-04 14:22:56 +000067 signalled_all.release()
Michael W. Hudson43220ea2004-08-03 14:37:14 +000068
69 def spawnSignallingThread(self):
70 thread.start_new_thread(send_signals, ())
Tim Peters6db15d72004-08-04 02:36:18 +000071
Michael W. Hudson43220ea2004-08-03 14:37:14 +000072
73def test_main():
Michael W. Hudson574a2512004-08-04 14:22:56 +000074 global signal_blackboard
Tim Petersd1b78272004-08-07 06:03:09 +000075
Michael W. Hudson574a2512004-08-04 14:22:56 +000076 signal_blackboard = { signal.SIGUSR1 : {'tripped': 0, 'tripped_by': 0 },
77 signal.SIGUSR2 : {'tripped': 0, 'tripped_by': 0 },
78 signal.SIGALRM : {'tripped': 0, 'tripped_by': 0 } }
79
Ezio Melottidde5b942010-02-03 05:37:26 +000080 oldsigs = registerSignals(handle_signals, handle_signals, handle_signals)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000081 try:
Michael W. Hudson574a2512004-08-04 14:22:56 +000082 run_unittest(ThreadSignals)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000083 finally:
Ezio Melottidde5b942010-02-03 05:37:26 +000084 registerSignals(*oldsigs)
Michael W. Hudson43220ea2004-08-03 14:37:14 +000085
86if __name__ == '__main__':
87 test_main()