10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""PyUnit testing that threads honor our signal semantics""" 20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 30a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport unittest 40a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport signal 50a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os 60a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys 70a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom test.test_support import run_unittest, import_module, reap_threads 80a8c90248264a8b26970b4473770bcc3df8515fJosh Gaothread = import_module('thread') 90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 100a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos': 110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise unittest.SkipTest, "Can't test signal on %s" % sys.platform 120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 130a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoprocess_pid = os.getpid() 140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaosignalled_all=thread.allocate_lock() 150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 170a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef registerSignals(for_usr1, for_usr2, for_alrm): 180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao usr1 = signal.signal(signal.SIGUSR1, for_usr1) 190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao usr2 = signal.signal(signal.SIGUSR2, for_usr2) 200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao alrm = signal.signal(signal.SIGALRM, for_alrm) 210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return usr1, usr2, alrm 220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# The signal handler. Just note that the signal occurred and 250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# from who. 260a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef handle_signals(sig,frame): 270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal_blackboard[sig]['tripped'] += 1 280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal_blackboard[sig]['tripped_by'] = thread.get_ident() 290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# a function that will be spawned as a separate thread. 310a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef send_signals(): 320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.kill(process_pid, signal.SIGUSR1) 330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.kill(process_pid, signal.SIGUSR2) 340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signalled_all.release() 350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 360a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass ThreadSignals(unittest.TestCase): 370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """Test signal handling semantics of threads. 380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao We spawn a thread, have the thread send two signals, and 390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao wait for it to finish. Check that we got both signals 400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao and that they were run by the main thread. 410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """ 420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao @reap_threads 430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def test_signals(self): 440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signalled_all.acquire() 450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.spawnSignallingThread() 460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signalled_all.acquire() 470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # the signals that we asked the kernel to send 480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # will come back, but we don't know when. 490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # (it might even be after the thread exits 500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # and might be out of order.) If we haven't seen 510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # the signals yet, send yet another signal and 520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # wait for it return. 530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if signal_blackboard[signal.SIGUSR1]['tripped'] == 0 \ 540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao or signal_blackboard[signal.SIGUSR2]['tripped'] == 0: 550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal.alarm(1) 560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal.pause() 570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal.alarm(0) 580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped'], 1) 600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped_by'], 610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao thread.get_ident()) 620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped'], 1) 630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.assertEqual( signal_blackboard[signal.SIGUSR2]['tripped_by'], 640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao thread.get_ident()) 650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signalled_all.release() 660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def spawnSignallingThread(self): 680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao thread.start_new_thread(send_signals, ()) 690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 710a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef test_main(): 720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao global signal_blackboard 730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal_blackboard = { signal.SIGUSR1 : {'tripped': 0, 'tripped_by': 0 }, 750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal.SIGUSR2 : {'tripped': 0, 'tripped_by': 0 }, 760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao signal.SIGALRM : {'tripped': 0, 'tripped_by': 0 } } 770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao oldsigs = registerSignals(handle_signals, handle_signals, handle_signals) 790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao run_unittest(ThreadSignals) 810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao finally: 820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao registerSignals(*oldsigs) 830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 840a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__': 850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao test_main() 86