| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  | """PyUnit testing that threads honor our signal semantics""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import signal | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2004-08-03 16:14:13 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  | from test.support import threading_helper | 
					
						
							| 
									
										
										
										
											2017-09-18 23:50:44 +02:00
										 |  |  | import _thread as thread | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 00:59:39 +01:00
										 |  |  | if (sys.platform[:3] == 'win'): | 
					
						
							| 
									
										
											  
											
												Merged revisions 70554,70588-70589,70598,70605,70611-70621,70623-70624,70626-70627 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
  r70554 | benjamin.peterson | 2009-03-23 16:25:15 -0500 (Mon, 23 Mar 2009) | 1 line
  complain when there's no last exception
........
  r70588 | benjamin.peterson | 2009-03-24 17:56:32 -0500 (Tue, 24 Mar 2009) | 1 line
  fix newline issue in test summary
........
  r70589 | benjamin.peterson | 2009-03-24 18:07:07 -0500 (Tue, 24 Mar 2009) | 1 line
  another style nit
........
  r70598 | benjamin.peterson | 2009-03-25 16:24:04 -0500 (Wed, 25 Mar 2009) | 1 line
  add shorthands for expected failures and unexpected success
........
  r70605 | benjamin.peterson | 2009-03-26 11:32:23 -0500 (Thu, 26 Mar 2009) | 1 line
  remove uneeded function
........
  r70611 | benjamin.peterson | 2009-03-26 13:35:37 -0500 (Thu, 26 Mar 2009) | 1 line
  add much better tests for python version information parsing
........
  r70612 | benjamin.peterson | 2009-03-26 13:55:48 -0500 (Thu, 26 Mar 2009) | 1 line
  more and more implementations now support sys.subversion
........
  r70613 | benjamin.peterson | 2009-03-26 13:58:30 -0500 (Thu, 26 Mar 2009) | 1 line
  roll old test in with new one
........
  r70614 | benjamin.peterson | 2009-03-26 14:09:21 -0500 (Thu, 26 Mar 2009) | 1 line
  add support for PyPy
........
  r70615 | benjamin.peterson | 2009-03-26 14:58:18 -0500 (Thu, 26 Mar 2009) | 5 lines
  add some useful utilities for skipping tests with unittest's new skipping ability
  most significantly apply a modified portion of the patch from #4242 with
  patches for skipping implementation details
........
  r70616 | benjamin.peterson | 2009-03-26 15:05:50 -0500 (Thu, 26 Mar 2009) | 1 line
  rename TestCase.skip() to skipTest() because it causes annoying problems with trial #5571
........
  r70617 | benjamin.peterson | 2009-03-26 15:17:27 -0500 (Thu, 26 Mar 2009) | 1 line
  apply the second part of #4242's patch; classify all the implementation details in test_descr
........
  r70618 | benjamin.peterson | 2009-03-26 15:48:25 -0500 (Thu, 26 Mar 2009) | 1 line
  remove test_support.TestSkipped and just use unittest.SkipTest
........
  r70619 | benjamin.peterson | 2009-03-26 15:49:40 -0500 (Thu, 26 Mar 2009) | 1 line
  fix naming
........
  r70620 | benjamin.peterson | 2009-03-26 16:10:30 -0500 (Thu, 26 Mar 2009) | 1 line
  fix incorrect auto-translation of TestSkipped -> unittest.SkipTest
........
  r70621 | benjamin.peterson | 2009-03-26 16:11:16 -0500 (Thu, 26 Mar 2009) | 1 line
  must pass argument to get expected behavior ;)
........
  r70623 | benjamin.peterson | 2009-03-26 16:30:10 -0500 (Thu, 26 Mar 2009) | 1 line
  add missing import
........
  r70624 | benjamin.peterson | 2009-03-26 16:30:54 -0500 (Thu, 26 Mar 2009) | 1 line
  ** is required here
........
  r70626 | benjamin.peterson | 2009-03-26 16:40:29 -0500 (Thu, 26 Mar 2009) | 1 line
  update email tests to use SkipTest
........
  r70627 | benjamin.peterson | 2009-03-26 16:44:43 -0500 (Thu, 26 Mar 2009) | 1 line
  fix another name
........
											
										 
											2009-03-28 21:42:05 +00:00
										 |  |  |     raise unittest.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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-30 14:53:09 +02:00
										 |  |  | USING_PTHREAD_COND = (sys.thread_info.name == 'pthread' | 
					
						
							|  |  |  |                       and sys.thread_info.lock == 'mutex+cond') | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-15 18:46:22 +00:00
										 |  |  | def registerSignals(for_usr1, for_usr2, for_alrm): | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  |     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(): | 
					
						
							| 
									
										
										
										
											2024-03-11 20:39:17 +00:00
										 |  |  |     # We use `raise_signal` rather than `kill` because: | 
					
						
							|  |  |  |     #   * It verifies that a signal delivered to a background thread still has | 
					
						
							|  |  |  |     #     its Python-level handler called on the main thread. | 
					
						
							|  |  |  |     #   * It ensures the signal is handled before the thread exits. | 
					
						
							|  |  |  |     signal.raise_signal(signal.SIGUSR1) | 
					
						
							|  |  |  |     signal.raise_signal(signal.SIGUSR2) | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  |     signalled_all.release() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 20:28:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-07 10:22:47 +03:00
										 |  |  | @threading_helper.requires_working_threading() | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  | class ThreadSignals(unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  |     def test_signals(self): | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |         with threading_helper.wait_threads_exit(): | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |             # Test signal handling semantics of threads. | 
					
						
							| 
									
										
										
										
											2024-03-11 20:39:17 +00:00
										 |  |  |             # We spawn a thread, have the thread send itself two signals, and | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |             # wait for it to finish. Check that we got both signals | 
					
						
							|  |  |  |             # and that they were run by the main thread. | 
					
						
							|  |  |  |             signalled_all.acquire() | 
					
						
							|  |  |  |             self.spawnSignallingThread() | 
					
						
							|  |  |  |             signalled_all.acquire() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |     def alarm_interrupt(self, sig, frame): | 
					
						
							|  |  |  |         raise KeyboardInterrupt | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-19 23:58:51 +02:00
										 |  |  |     @unittest.skipIf(USING_PTHREAD_COND, | 
					
						
							|  |  |  |                      'POSIX condition variables cannot be interrupted') | 
					
						
							| 
									
										
										
										
											2018-09-12 13:48:03 -07:00
										 |  |  |     @unittest.skipIf(sys.platform.startswith('linux') and | 
					
						
							|  |  |  |                      not sys.thread_info.version, | 
					
						
							|  |  |  |                      'Issue 34004: musl does not allow interruption of locks ' | 
					
						
							|  |  |  |                      'by signals.') | 
					
						
							| 
									
										
										
										
											2014-02-18 09:19:48 +01:00
										 |  |  |     # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD | 
					
						
							|  |  |  |     @unittest.skipIf(sys.platform.startswith('openbsd'), | 
					
						
							|  |  |  |                      'lock cannot be interrupted on OpenBSD') | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |     def test_lock_acquire_interruption(self): | 
					
						
							|  |  |  |         # Mimic receiving a SIGINT (KeyboardInterrupt) with SIGALRM while stuck | 
					
						
							|  |  |  |         # in a deadlock. | 
					
						
							| 
									
										
										
										
											2011-03-13 19:14:21 +01:00
										 |  |  |         # XXX this test can fail when the legacy (non-semaphore) implementation | 
					
						
							|  |  |  |         # of locks is used in thread_pthread.h, see issue #11223. | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         oldalrm = signal.signal(signal.SIGALRM, self.alarm_interrupt) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             lock = thread.allocate_lock() | 
					
						
							|  |  |  |             lock.acquire() | 
					
						
							|  |  |  |             signal.alarm(1) | 
					
						
							| 
									
										
										
										
											2018-12-17 09:36:36 +01:00
										 |  |  |             t1 = time.monotonic() | 
					
						
							| 
									
										
										
										
											2011-03-13 19:14:21 +01:00
										 |  |  |             self.assertRaises(KeyboardInterrupt, lock.acquire, timeout=5) | 
					
						
							| 
									
										
										
										
											2018-12-17 09:36:36 +01:00
										 |  |  |             dt = time.monotonic() - t1 | 
					
						
							| 
									
										
										
										
											2011-03-13 19:14:21 +01:00
										 |  |  |             # Checking that KeyboardInterrupt was raised is not sufficient. | 
					
						
							|  |  |  |             # We want to assert that lock.acquire() was interrupted because | 
					
						
							|  |  |  |             # of the signal, not that the signal handler was called immediately | 
					
						
							|  |  |  |             # after timeout return of lock.acquire() (which can fool assertRaises). | 
					
						
							|  |  |  |             self.assertLess(dt, 3.0) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         finally: | 
					
						
							| 
									
										
										
										
											2017-09-19 09:36:54 -07:00
										 |  |  |             signal.alarm(0) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |             signal.signal(signal.SIGALRM, oldalrm) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-19 23:58:51 +02:00
										 |  |  |     @unittest.skipIf(USING_PTHREAD_COND, | 
					
						
							|  |  |  |                      'POSIX condition variables cannot be interrupted') | 
					
						
							| 
									
										
										
										
											2018-09-12 13:48:03 -07:00
										 |  |  |     @unittest.skipIf(sys.platform.startswith('linux') and | 
					
						
							|  |  |  |                      not sys.thread_info.version, | 
					
						
							|  |  |  |                      'Issue 34004: musl does not allow interruption of locks ' | 
					
						
							|  |  |  |                      'by signals.') | 
					
						
							| 
									
										
										
										
											2014-02-18 09:19:48 +01:00
										 |  |  |     # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD | 
					
						
							|  |  |  |     @unittest.skipIf(sys.platform.startswith('openbsd'), | 
					
						
							|  |  |  |                      'lock cannot be interrupted on OpenBSD') | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |     def test_rlock_acquire_interruption(self): | 
					
						
							|  |  |  |         # Mimic receiving a SIGINT (KeyboardInterrupt) with SIGALRM while stuck | 
					
						
							|  |  |  |         # in a deadlock. | 
					
						
							| 
									
										
										
										
											2011-03-13 19:14:21 +01:00
										 |  |  |         # XXX this test can fail when the legacy (non-semaphore) implementation | 
					
						
							|  |  |  |         # of locks is used in thread_pthread.h, see issue #11223. | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         oldalrm = signal.signal(signal.SIGALRM, self.alarm_interrupt) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             rlock = thread.RLock() | 
					
						
							|  |  |  |             # For reentrant locks, the initial acquisition must be in another | 
					
						
							|  |  |  |             # thread. | 
					
						
							|  |  |  |             def other_thread(): | 
					
						
							|  |  |  |                 rlock.acquire() | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |             with threading_helper.wait_threads_exit(): | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |                 thread.start_new_thread(other_thread, ()) | 
					
						
							|  |  |  |                 # Wait until we can't acquire it without blocking... | 
					
						
							|  |  |  |                 while rlock.acquire(blocking=False): | 
					
						
							|  |  |  |                     rlock.release() | 
					
						
							|  |  |  |                     time.sleep(0.01) | 
					
						
							|  |  |  |                 signal.alarm(1) | 
					
						
							| 
									
										
										
										
											2018-12-17 09:36:36 +01:00
										 |  |  |                 t1 = time.monotonic() | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |                 self.assertRaises(KeyboardInterrupt, rlock.acquire, timeout=5) | 
					
						
							| 
									
										
										
										
											2018-12-17 09:36:36 +01:00
										 |  |  |                 dt = time.monotonic() - t1 | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |                 # See rationale above in test_lock_acquire_interruption | 
					
						
							|  |  |  |                 self.assertLess(dt, 3.0) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         finally: | 
					
						
							| 
									
										
										
										
											2017-09-19 09:36:54 -07:00
										 |  |  |             signal.alarm(0) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |             signal.signal(signal.SIGALRM, oldalrm) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def acquire_retries_on_intr(self, lock): | 
					
						
							|  |  |  |         self.sig_recvd = False | 
					
						
							|  |  |  |         def my_handler(signal, frame): | 
					
						
							|  |  |  |             self.sig_recvd = True | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         old_handler = signal.signal(signal.SIGUSR1, my_handler) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             def other_thread(): | 
					
						
							|  |  |  |                 # Acquire the lock in a non-main thread, so this test works for | 
					
						
							|  |  |  |                 # RLocks. | 
					
						
							|  |  |  |                 lock.acquire() | 
					
						
							|  |  |  |                 # Wait until the main thread is blocked in the lock acquire, and | 
					
						
							|  |  |  |                 # then wake it up with this. | 
					
						
							|  |  |  |                 time.sleep(0.5) | 
					
						
							|  |  |  |                 os.kill(process_pid, signal.SIGUSR1) | 
					
						
							|  |  |  |                 # Let the main thread take the interrupt, handle it, and retry | 
					
						
							|  |  |  |                 # the lock acquisition.  Then we'll let it run. | 
					
						
							|  |  |  |                 time.sleep(0.5) | 
					
						
							|  |  |  |                 lock.release() | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |             with threading_helper.wait_threads_exit(): | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |                 thread.start_new_thread(other_thread, ()) | 
					
						
							|  |  |  |                 # Wait until we can't acquire it without blocking... | 
					
						
							|  |  |  |                 while lock.acquire(blocking=False): | 
					
						
							|  |  |  |                     lock.release() | 
					
						
							|  |  |  |                     time.sleep(0.01) | 
					
						
							|  |  |  |                 result = lock.acquire()  # Block while we receive a signal. | 
					
						
							|  |  |  |                 self.assertTrue(self.sig_recvd) | 
					
						
							|  |  |  |                 self.assertTrue(result) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         finally: | 
					
						
							|  |  |  |             signal.signal(signal.SIGUSR1, old_handler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_lock_acquire_retries_on_intr(self): | 
					
						
							|  |  |  |         self.acquire_retries_on_intr(thread.allocate_lock()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_rlock_acquire_retries_on_intr(self): | 
					
						
							|  |  |  |         self.acquire_retries_on_intr(thread.RLock()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_interrupted_timed_acquire(self): | 
					
						
							|  |  |  |         # Test to make sure we recompute lock acquisition timeouts when we | 
					
						
							|  |  |  |         # receive a signal.  Check this by repeatedly interrupting a lock | 
					
						
							|  |  |  |         # acquire in the main thread, and make sure that the lock acquire times | 
					
						
							|  |  |  |         # out after the right amount of time. | 
					
						
							| 
									
										
										
										
											2010-12-15 23:38:50 +00:00
										 |  |  |         # NOTE: this test only behaves as expected if C signals get delivered | 
					
						
							|  |  |  |         # to the main thread.  Otherwise lock.acquire() itself doesn't get | 
					
						
							|  |  |  |         # interrupted and the test trivially succeeds. | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         self.start = None | 
					
						
							|  |  |  |         self.end = None | 
					
						
							|  |  |  |         self.sigs_recvd = 0 | 
					
						
							|  |  |  |         done = thread.allocate_lock() | 
					
						
							|  |  |  |         done.acquire() | 
					
						
							|  |  |  |         lock = thread.allocate_lock() | 
					
						
							|  |  |  |         lock.acquire() | 
					
						
							|  |  |  |         def my_handler(signum, frame): | 
					
						
							|  |  |  |             self.sigs_recvd += 1 | 
					
						
							|  |  |  |         old_handler = signal.signal(signal.SIGUSR1, my_handler) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             def timed_acquire(): | 
					
						
							| 
									
										
										
										
											2018-12-17 09:36:36 +01:00
										 |  |  |                 self.start = time.monotonic() | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |                 lock.acquire(timeout=0.5) | 
					
						
							| 
									
										
										
										
											2018-12-17 09:36:36 +01:00
										 |  |  |                 self.end = time.monotonic() | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |             def send_signals(): | 
					
						
							|  |  |  |                 for _ in range(40): | 
					
						
							| 
									
										
										
										
											2010-12-15 23:38:50 +00:00
										 |  |  |                     time.sleep(0.02) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |                     os.kill(process_pid, signal.SIGUSR1) | 
					
						
							|  |  |  |                 done.release() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |             with threading_helper.wait_threads_exit(): | 
					
						
							| 
									
										
										
										
											2017-09-14 13:07:24 -07:00
										 |  |  |                 # Send the signals from the non-main thread, since the main thread | 
					
						
							|  |  |  |                 # is the only one that can process signals. | 
					
						
							|  |  |  |                 thread.start_new_thread(send_signals, ()) | 
					
						
							|  |  |  |                 timed_acquire() | 
					
						
							|  |  |  |                 # Wait for thread to finish | 
					
						
							|  |  |  |                 done.acquire() | 
					
						
							|  |  |  |                 # This allows for some timing and scheduling imprecision | 
					
						
							|  |  |  |                 self.assertLess(self.end - self.start, 2.0) | 
					
						
							|  |  |  |                 self.assertGreater(self.end - self.start, 0.3) | 
					
						
							|  |  |  |                 # If the signal is received several times before PyErr_CheckSignals() | 
					
						
							|  |  |  |                 # is called, the handler will get called less than 40 times. Just | 
					
						
							|  |  |  |                 # check it's been called at least once. | 
					
						
							|  |  |  |                 self.assertGreater(self.sigs_recvd, 0) | 
					
						
							| 
									
										
										
										
											2010-12-15 22:59:16 +00:00
										 |  |  |         finally: | 
					
						
							|  |  |  |             signal.signal(signal.SIGUSR1, old_handler) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 15:27:33 +03:00
										 |  |  | def setUpModule(): | 
					
						
							| 
									
										
										
										
											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 } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-15 18:46:22 +00:00
										 |  |  |     oldsigs = registerSignals(handle_signals, handle_signals, handle_signals) | 
					
						
							| 
									
										
										
										
											2021-09-19 15:27:33 +03:00
										 |  |  |     unittest.addModuleCleanup(registerSignals, *oldsigs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-03 14:37:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2021-09-19 15:27:33 +03:00
										 |  |  |     unittest.main() |