2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								"""PyUnit testing that threads honor our signal semantics"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import unittest
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import thread
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import signal
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import os
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 16:14:13 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import sys
							 | 
						
					
						
							
								
									
										
										
										
											2009-03-26 20:48:25 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from test.test_support import run_unittest, SkipTest
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 15:35:29 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos':
							 | 
						
					
						
							
								
									
										
										
										
											2009-03-26 20:48:25 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    raise SkipTest, "Can't test signal on %s" % sys.platform
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 15:35:29 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								process_pid = os.getpid()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								signalled_all=thread.allocate_lock()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def registerSignals((for_usr1, for_usr2, for_alrm)):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    usr1 = signal.signal(signal.SIGUSR1, for_usr1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    usr2 = signal.signal(signal.SIGUSR2, for_usr2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    alrm = signal.signal(signal.SIGALRM, for_alrm)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return usr1, usr2, alrm
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2005-10-28 14:39:47 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# The signal handler. Just note that the signal occurred and
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# from who.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def handle_signals(sig,frame):
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 02:36:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    signal_blackboard[sig]['tripped'] += 1
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    signal_blackboard[sig]['tripped_by'] = thread.get_ident()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# a function that will be spawned as a separate thread.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def send_signals():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    os.kill(process_pid, signal.SIGUSR1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    os.kill(process_pid, signal.SIGUSR2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    signalled_all.release()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class ThreadSignals(unittest.TestCase):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """Test signal handling semantics of threads.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       We spawn a thread, have the thread send two signals, and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       wait for it to finish. Check that we got both signals
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       and that they were run by the main thread.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def test_signals(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        signalled_all.acquire()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.spawnSignallingThread()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        signalled_all.acquire()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # the signals that we asked the kernel to send
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # will come back, but we don't know when.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # (it might even be after the thread exits
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # and might be out of order.)  If we haven't seen
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # the signals yet, send yet another signal and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # wait for it return.
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												test_signal:  Signal handling on the Tru64 buildbot
appears to be utterly insane.  Plug some theoretical
insecurities in the test script:
- Verify that the SIGALRM handler was actually installed.
- Don't call alarm() before the handler is installed.
- Move everything that can fail inside the try/finally,
  so the test cleans up after itself more often.
- Try sending all the expected signals in
  force_test_exit(), not just SIGALRM.  Since that was
  fixed to actually send SIGALRM (instead of invisibly
  dying with an AttributeError), we've seen that sending
  SIGALRM alone does not stop this from hanging.
- Move the "kill the child" business into the finally
  clause, so the child doesn't survive test failure
  to send SIGALRM to other tests later (there are also
  baffling SIGALRM-related failures in test_socket).
- Cancel the alarm in the finally clause -- if the
  test dies early, we again don't want SIGALRM showing
  up to confuse a later test.
Alas, this still relies on timing luck wrt the spawned
script that sends the test signals, but it's hard to see
how waiting for seconds can so often be so unlucky.
test_threadedsignals:  curiously, this test never fails
on Tru64, but doesn't normally signal SIGALRM.  Anyway,
fixed an obvious (but probably inconsequential) logic
error.
											
										 
										
											2006-08-12 04:42:47 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if signal_blackboard[signal.SIGUSR1]['tripped'] == 0 \
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								           or signal_blackboard[signal.SIGUSR2]['tripped'] == 0:
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 02:36:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            signal.alarm(1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            signal.pause()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            signal.alarm(0)
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped'], 1)
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 02:36:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped_by'],
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           thread.get_ident())
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped'], 1)
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 02:36:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped_by'],
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           thread.get_ident())
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 14:22:56 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        signalled_all.release()
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def spawnSignallingThread(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        thread.start_new_thread(send_signals, ())
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 02:36:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def test_main():
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 14:22:56 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    global signal_blackboard
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-07 06:03:09 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 14:22:56 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    signal_blackboard = { signal.SIGUSR1 : {'tripped': 0, 'tripped_by': 0 },
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          signal.SIGUSR2 : {'tripped': 0, 'tripped_by': 0 },
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          signal.SIGALRM : {'tripped': 0, 'tripped_by': 0 } }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    oldsigs = registerSignals((handle_signals, handle_signals, handle_signals))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    try:
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-04 14:22:56 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        run_unittest(ThreadSignals)
							 | 
						
					
						
							
								
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        registerSignals(oldsigs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								if __name__ == '__main__':
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    test_main()
							 |