| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 1 | import unittest | 
| Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 2 | from test import support | 
| Raymond Hettinger | 722d8c3 | 2009-06-18 22:21:03 +0000 | [diff] [blame] | 3 | from contextlib import closing | 
| Christian Heimes | cc47b05 | 2008-03-25 14:56:36 +0000 | [diff] [blame] | 4 | import gc | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 5 | import pickle | 
 | 6 | import select | 
| Guido van Rossum | 4f17e3e | 1995-03-16 15:07:38 +0000 | [diff] [blame] | 7 | import signal | 
| Victor Stinner | d49b1f1 | 2011-05-08 02:03:15 +0200 | [diff] [blame] | 8 | import struct | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 9 | import subprocess | 
 | 10 | import traceback | 
| Christian Heimes | c06950e | 2008-02-28 21:17:00 +0000 | [diff] [blame] | 11 | import sys, os, time, errno | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 12 | from test.script_helper import assert_python_ok, spawn_python | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 13 | try: | 
 | 14 |     import threading | 
 | 15 | except ImportError: | 
 | 16 |     threading = None | 
| Christian Heimes | c06950e | 2008-02-28 21:17:00 +0000 | [diff] [blame] | 17 |  | 
| Brian Curtin | 912443c | 2010-09-06 16:10:04 +0000 | [diff] [blame] | 18 | if sys.platform in ('os2', 'riscos'): | 
 | 19 |     raise unittest.SkipTest("Can't test signal on %s" % sys.platform) | 
| Christian Heimes | c06950e | 2008-02-28 21:17:00 +0000 | [diff] [blame] | 20 |  | 
| Guido van Rossum | cc5a91d | 1997-04-16 00:29:15 +0000 | [diff] [blame] | 21 |  | 
| Armin Rigo | 8b2cbfd | 2004-08-07 21:27:43 +0000 | [diff] [blame] | 22 | class HandlerBCalled(Exception): | 
 | 23 |     pass | 
| Guido van Rossum | 4f17e3e | 1995-03-16 15:07:38 +0000 | [diff] [blame] | 24 |  | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 25 |  | 
 | 26 | def exit_subprocess(): | 
 | 27 |     """Use os._exit(0) to exit the current subprocess. | 
 | 28 |  | 
 | 29 |     Otherwise, the test catches the SystemExit and continues executing | 
 | 30 |     in parallel with the original test, so you wind up with an | 
 | 31 |     exponential number of tests running concurrently. | 
 | 32 |     """ | 
 | 33 |     os._exit(0) | 
 | 34 |  | 
 | 35 |  | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 36 | def ignoring_eintr(__func, *args, **kwargs): | 
 | 37 |     try: | 
 | 38 |         return __func(*args, **kwargs) | 
| Neal Norwitz | f5c7c2e | 2008-04-05 04:47:45 +0000 | [diff] [blame] | 39 |     except EnvironmentError as e: | 
 | 40 |         if e.errno != errno.EINTR: | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 41 |             raise | 
 | 42 |         return None | 
 | 43 |  | 
 | 44 |  | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 45 | @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 46 | class InterProcessSignalTests(unittest.TestCase): | 
 | 47 |     MAX_DURATION = 20   # Entire test should last at most 20 sec. | 
| Guido van Rossum | 4f17e3e | 1995-03-16 15:07:38 +0000 | [diff] [blame] | 48 |  | 
| Christian Heimes | cc47b05 | 2008-03-25 14:56:36 +0000 | [diff] [blame] | 49 |     def setUp(self): | 
 | 50 |         self.using_gc = gc.isenabled() | 
 | 51 |         gc.disable() | 
 | 52 |  | 
 | 53 |     def tearDown(self): | 
 | 54 |         if self.using_gc: | 
 | 55 |             gc.enable() | 
 | 56 |  | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 57 |     def format_frame(self, frame, limit=None): | 
 | 58 |         return ''.join(traceback.format_stack(frame, limit=limit)) | 
 | 59 |  | 
 | 60 |     def handlerA(self, signum, frame): | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 61 |         self.a_called = True | 
| Guido van Rossum | 4f17e3e | 1995-03-16 15:07:38 +0000 | [diff] [blame] | 62 |  | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 63 |     def handlerB(self, signum, frame): | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 64 |         self.b_called = True | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 65 |         raise HandlerBCalled(signum, self.format_frame(frame)) | 
| Neal Norwitz | 9730bcb | 2006-01-23 07:50:06 +0000 | [diff] [blame] | 66 |  | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 67 |     def wait(self, child): | 
 | 68 |         """Wait for child to finish, ignoring EINTR.""" | 
 | 69 |         while True: | 
 | 70 |             try: | 
 | 71 |                 child.wait() | 
 | 72 |                 return | 
 | 73 |             except OSError as e: | 
 | 74 |                 if e.errno != errno.EINTR: | 
 | 75 |                     raise | 
| Fred Drake | 004d5e6 | 2000-10-23 17:22:08 +0000 | [diff] [blame] | 76 |  | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 77 |     def run_test(self): | 
 | 78 |         # Install handlers. This function runs in a sub-process, so we | 
 | 79 |         # don't worry about re-setting the default handlers. | 
 | 80 |         signal.signal(signal.SIGHUP, self.handlerA) | 
 | 81 |         signal.signal(signal.SIGUSR1, self.handlerB) | 
 | 82 |         signal.signal(signal.SIGUSR2, signal.SIG_IGN) | 
 | 83 |         signal.signal(signal.SIGALRM, signal.default_int_handler) | 
| Michael W. Hudson | 5c26e86 | 2004-06-11 18:09:28 +0000 | [diff] [blame] | 84 |  | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 85 |         # Variables the signals will modify: | 
 | 86 |         self.a_called = False | 
 | 87 |         self.b_called = False | 
| Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 88 |  | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 89 |         # Let the sub-processes know who to send signals to. | 
 | 90 |         pid = os.getpid() | 
| Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 91 |  | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 92 |         child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)]) | 
 | 93 |         if child: | 
 | 94 |             self.wait(child) | 
 | 95 |             if not self.a_called: | 
 | 96 |                 time.sleep(1)  # Give the signal time to be delivered. | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 97 |         self.assertTrue(self.a_called) | 
 | 98 |         self.assertFalse(self.b_called) | 
 | 99 |         self.a_called = False | 
| Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 100 |  | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 101 |         # Make sure the signal isn't delivered while the previous | 
 | 102 |         # Popen object is being destroyed, because __del__ swallows | 
 | 103 |         # exceptions. | 
 | 104 |         del child | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 105 |         try: | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 106 |             child = subprocess.Popen(['kill', '-USR1', str(pid)]) | 
 | 107 |             # This wait should be interrupted by the signal's exception. | 
 | 108 |             self.wait(child) | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 109 |             time.sleep(1)  # Give the signal time to be delivered. | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 110 |             self.fail('HandlerBCalled exception not thrown') | 
 | 111 |         except HandlerBCalled: | 
 | 112 |             self.assertTrue(self.b_called) | 
 | 113 |             self.assertFalse(self.a_called) | 
| Thomas Wouters | 0e3f591 | 2006-08-11 14:57:12 +0000 | [diff] [blame] | 114 |  | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 115 |         child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)]) | 
 | 116 |         if child: | 
 | 117 |             self.wait(child)  # Nothing should happen. | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 118 |  | 
 | 119 |         try: | 
 | 120 |             signal.alarm(1) | 
 | 121 |             # The race condition in pause doesn't matter in this case, | 
 | 122 |             # since alarm is going to raise a KeyboardException, which | 
 | 123 |             # will skip the call. | 
 | 124 |             signal.pause() | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 125 |             # But if another signal arrives before the alarm, pause | 
 | 126 |             # may return early. | 
 | 127 |             time.sleep(1) | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 128 |         except KeyboardInterrupt: | 
| Victor Stinner | 3a7f0f0 | 2011-05-08 02:10:36 +0200 | [diff] [blame] | 129 |             pass | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 130 |         except: | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 131 |             self.fail("Some other exception woke us from pause: %s" % | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 132 |                       traceback.format_exc()) | 
 | 133 |         else: | 
| Benjamin Peterson | ad9d48d | 2008-04-02 21:49:44 +0000 | [diff] [blame] | 134 |             self.fail("pause returned of its own accord, and the signal" | 
 | 135 |                       " didn't arrive after another second.") | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 136 |  | 
| R. David Murray | 44546f8 | 2010-04-21 01:59:28 +0000 | [diff] [blame] | 137 |     # Issue 3864, unknown if this affects earlier versions of freebsd also | 
 | 138 |     @unittest.skipIf(sys.platform=='freebsd6', | 
 | 139 |         'inter process signals not reliable (do not mix well with threading) ' | 
 | 140 |         'on freebsd6') | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 141 |     def test_main(self): | 
 | 142 |         # This function spawns a child process to insulate the main | 
 | 143 |         # test-running process from all the signals. It then | 
 | 144 |         # communicates with that child process over a pipe and | 
 | 145 |         # re-raises information about any exceptions the child | 
 | 146 |         # throws. The real work happens in self.run_test(). | 
 | 147 |         os_done_r, os_done_w = os.pipe() | 
| Raymond Hettinger | 686057b | 2009-06-04 00:11:54 +0000 | [diff] [blame] | 148 |         with closing(os.fdopen(os_done_r, 'rb')) as done_r, \ | 
 | 149 |              closing(os.fdopen(os_done_w, 'wb')) as done_w: | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 150 |             child = os.fork() | 
 | 151 |             if child == 0: | 
 | 152 |                 # In the child process; run the test and report results | 
 | 153 |                 # through the pipe. | 
 | 154 |                 try: | 
 | 155 |                     done_r.close() | 
 | 156 |                     # Have to close done_w again here because | 
 | 157 |                     # exit_subprocess() will skip the enclosing with block. | 
 | 158 |                     with closing(done_w): | 
 | 159 |                         try: | 
 | 160 |                             self.run_test() | 
 | 161 |                         except: | 
 | 162 |                             pickle.dump(traceback.format_exc(), done_w) | 
 | 163 |                         else: | 
 | 164 |                             pickle.dump(None, done_w) | 
 | 165 |                 except: | 
 | 166 |                     print('Uh oh, raised from pickle.') | 
 | 167 |                     traceback.print_exc() | 
 | 168 |                 finally: | 
 | 169 |                     exit_subprocess() | 
 | 170 |  | 
 | 171 |             done_w.close() | 
 | 172 |             # Block for up to MAX_DURATION seconds for the test to finish. | 
 | 173 |             r, w, x = select.select([done_r], [], [], self.MAX_DURATION) | 
 | 174 |             if done_r in r: | 
 | 175 |                 tb = pickle.load(done_r) | 
 | 176 |                 if tb: | 
 | 177 |                     self.fail(tb) | 
 | 178 |             else: | 
 | 179 |                 os.kill(child, signal.SIGKILL) | 
 | 180 |                 self.fail('Test deadlocked after %d seconds.' % | 
 | 181 |                           self.MAX_DURATION) | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 182 |  | 
 | 183 |  | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 184 | @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 185 | class PosixTests(unittest.TestCase): | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 186 |     def trivial_signal_handler(self, *args): | 
 | 187 |         pass | 
 | 188 |  | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 189 |     def test_out_of_range_signal_number_raises_error(self): | 
 | 190 |         self.assertRaises(ValueError, signal.getsignal, 4242) | 
 | 191 |  | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 192 |         self.assertRaises(ValueError, signal.signal, 4242, | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 193 |                           self.trivial_signal_handler) | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 194 |  | 
 | 195 |     def test_setting_signal_handler_to_none_raises_error(self): | 
 | 196 |         self.assertRaises(TypeError, signal.signal, | 
 | 197 |                           signal.SIGUSR1, None) | 
 | 198 |  | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 199 |     def test_getsignal(self): | 
 | 200 |         hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler) | 
| Ezio Melotti | 19f2aeb | 2010-11-21 01:30:29 +0000 | [diff] [blame] | 201 |         self.assertEqual(signal.getsignal(signal.SIGHUP), | 
 | 202 |                          self.trivial_signal_handler) | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 203 |         signal.signal(signal.SIGHUP, hup) | 
| Ezio Melotti | 19f2aeb | 2010-11-21 01:30:29 +0000 | [diff] [blame] | 204 |         self.assertEqual(signal.getsignal(signal.SIGHUP), hup) | 
| Christian Heimes | 4fbc72b | 2008-03-22 00:47:35 +0000 | [diff] [blame] | 205 |  | 
 | 206 |  | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 207 | @unittest.skipUnless(sys.platform == "win32", "Windows specific") | 
 | 208 | class WindowsSignalTests(unittest.TestCase): | 
 | 209 |     def test_issue9324(self): | 
| Brian Curtin | eccd4d9 | 2010-10-01 15:09:53 +0000 | [diff] [blame] | 210 |         # Updated for issue #10003, adding SIGBREAK | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 211 |         handler = lambda x, y: None | 
| Brian Curtin | eccd4d9 | 2010-10-01 15:09:53 +0000 | [diff] [blame] | 212 |         for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE, | 
 | 213 |                     signal.SIGILL, signal.SIGINT, signal.SIGSEGV, | 
 | 214 |                     signal.SIGTERM): | 
 | 215 |             # Set and then reset a handler for signals that work on windows | 
 | 216 |             signal.signal(sig, signal.signal(sig, handler)) | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 217 |  | 
 | 218 |         with self.assertRaises(ValueError): | 
 | 219 |             signal.signal(-1, handler) | 
| Brian Curtin | 80cd4bf | 2010-08-07 03:52:38 +0000 | [diff] [blame] | 220 |  | 
 | 221 |         with self.assertRaises(ValueError): | 
 | 222 |             signal.signal(7, handler) | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 223 |  | 
 | 224 |  | 
 | 225 | @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 226 | class WakeupSignalTests(unittest.TestCase): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 227 |     def check_wakeup(self, test_body, *signals): | 
 | 228 |         # use a subprocess to have only one thread | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 229 |         code = """if 1: | 
 | 230 |         import fcntl | 
 | 231 |         import os | 
 | 232 |         import signal | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 233 |         import struct | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 234 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 235 |         signals = {!r} | 
| Victor Stinner | c13ef66 | 2011-05-25 02:35:58 +0200 | [diff] [blame] | 236 |  | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 237 |         def handler(signum, frame): | 
 | 238 |             pass | 
 | 239 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 240 |         def check_signum(signals): | 
 | 241 |             data = os.read(read, len(signals)+1) | 
 | 242 |             raised = struct.unpack('%uB' % len(data), data) | 
 | 243 |             # We don't care of the signal delivery order (it's not portable or | 
 | 244 |             # reliable) | 
 | 245 |             raised = set(raised) | 
 | 246 |             signals = set(signals) | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 247 |             if raised != signals: | 
 | 248 |                 raise Exception("%r != %r" % (raised, signals)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 249 |  | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 250 |         {} | 
 | 251 |  | 
 | 252 |         signal.signal(signal.SIGALRM, handler) | 
 | 253 |         read, write = os.pipe() | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 254 |         for fd in (read, write): | 
 | 255 |             flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) | 
 | 256 |             flags = flags | os.O_NONBLOCK | 
 | 257 |             fcntl.fcntl(fd, fcntl.F_SETFL, flags) | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 258 |         signal.set_wakeup_fd(write) | 
 | 259 |  | 
 | 260 |         test() | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 261 |         check_signum(signals) | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 262 |  | 
 | 263 |         os.close(read) | 
 | 264 |         os.close(write) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 265 |         """.format(signals, test_body) | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 266 |  | 
 | 267 |         assert_python_ok('-c', code) | 
| Victor Stinner | d49b1f1 | 2011-05-08 02:03:15 +0200 | [diff] [blame] | 268 |  | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 269 |     def test_wakeup_fd_early(self): | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 270 |         self.check_wakeup("""def test(): | 
 | 271 |             import select | 
 | 272 |             import time | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 273 |  | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 274 |             TIMEOUT_FULL = 10 | 
 | 275 |             TIMEOUT_HALF = 5 | 
 | 276 |  | 
 | 277 |             signal.alarm(1) | 
 | 278 |             before_time = time.time() | 
 | 279 |             # We attempt to get a signal during the sleep, | 
 | 280 |             # before select is called | 
 | 281 |             time.sleep(TIMEOUT_FULL) | 
 | 282 |             mid_time = time.time() | 
 | 283 |             dt = mid_time - before_time | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 284 |             if dt >= TIMEOUT_HALF: | 
 | 285 |                 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF)) | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 286 |             select.select([read], [], [], TIMEOUT_FULL) | 
 | 287 |             after_time = time.time() | 
 | 288 |             dt = after_time - mid_time | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 289 |             if dt >= TIMEOUT_HALF: | 
 | 290 |                 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 291 |         """, signal.SIGALRM) | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 292 |  | 
 | 293 |     def test_wakeup_fd_during(self): | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 294 |         self.check_wakeup("""def test(): | 
 | 295 |             import select | 
 | 296 |             import time | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 297 |  | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 298 |             TIMEOUT_FULL = 10 | 
 | 299 |             TIMEOUT_HALF = 5 | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 300 |  | 
| Victor Stinner | e40b3aa | 2011-07-04 17:35:10 +0200 | [diff] [blame] | 301 |             signal.alarm(1) | 
 | 302 |             before_time = time.time() | 
 | 303 |             # We attempt to get a signal during the select call | 
 | 304 |             try: | 
 | 305 |                 select.select([read], [], [], TIMEOUT_FULL) | 
 | 306 |             except select.error: | 
 | 307 |                 pass | 
 | 308 |             else: | 
 | 309 |                 raise Exception("select.error not raised") | 
 | 310 |             after_time = time.time() | 
 | 311 |             dt = after_time - before_time | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 312 |             if dt >= TIMEOUT_HALF: | 
 | 313 |                 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 314 |         """, signal.SIGALRM) | 
| Victor Stinner | d49b1f1 | 2011-05-08 02:03:15 +0200 | [diff] [blame] | 315 |  | 
 | 316 |     def test_signum(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 317 |         self.check_wakeup("""def test(): | 
 | 318 |             signal.signal(signal.SIGUSR1, handler) | 
 | 319 |             os.kill(os.getpid(), signal.SIGUSR1) | 
 | 320 |             os.kill(os.getpid(), signal.SIGALRM) | 
 | 321 |         """, signal.SIGUSR1, signal.SIGALRM) | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 322 |  | 
| Victor Stinner | c13ef66 | 2011-05-25 02:35:58 +0200 | [diff] [blame] | 323 |     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | 
 | 324 |                          'need signal.pthread_sigmask()') | 
| Victor Stinner | c13ef66 | 2011-05-25 02:35:58 +0200 | [diff] [blame] | 325 |     def test_pending(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 326 |         self.check_wakeup("""def test(): | 
 | 327 |             signum1 = signal.SIGUSR1 | 
 | 328 |             signum2 = signal.SIGUSR2 | 
| Victor Stinner | c13ef66 | 2011-05-25 02:35:58 +0200 | [diff] [blame] | 329 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 330 |             signal.signal(signum1, handler) | 
 | 331 |             signal.signal(signum2, handler) | 
| Victor Stinner | c13ef66 | 2011-05-25 02:35:58 +0200 | [diff] [blame] | 332 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 333 |             signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2)) | 
 | 334 |             os.kill(os.getpid(), signum1) | 
 | 335 |             os.kill(os.getpid(), signum2) | 
 | 336 |             # Unblocking the 2 signals calls the C signal handler twice | 
 | 337 |             signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2)) | 
 | 338 |         """,  signal.SIGUSR1, signal.SIGUSR2) | 
| Victor Stinner | c13ef66 | 2011-05-25 02:35:58 +0200 | [diff] [blame] | 339 |  | 
| Christian Heimes | 5fb7c2a | 2007-12-24 08:52:31 +0000 | [diff] [blame] | 340 |  | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 341 | @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 342 | class SiginterruptTest(unittest.TestCase): | 
| Jean-Paul Calderone | 9c39bc7 | 2010-05-09 03:25:16 +0000 | [diff] [blame] | 343 |  | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 344 |     def readpipe_interrupted(self, interrupt): | 
| Jean-Paul Calderone | 9c39bc7 | 2010-05-09 03:25:16 +0000 | [diff] [blame] | 345 |         """Perform a read during which a signal will arrive.  Return True if the | 
 | 346 |         read is interrupted by the signal and raises an exception.  Return False | 
 | 347 |         if it returns normally. | 
 | 348 |         """ | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 349 |         # use a subprocess to have only one thread, to have a timeout on the | 
 | 350 |         # blocking read and to not touch signal handling in this process | 
 | 351 |         code = """if 1: | 
 | 352 |             import errno | 
 | 353 |             import os | 
 | 354 |             import signal | 
 | 355 |             import sys | 
| Jean-Paul Calderone | 9c39bc7 | 2010-05-09 03:25:16 +0000 | [diff] [blame] | 356 |  | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 357 |             interrupt = %r | 
 | 358 |             r, w = os.pipe() | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 359 |  | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 360 |             def handler(signum, frame): | 
 | 361 |                 pass | 
 | 362 |  | 
 | 363 |             signal.signal(signal.SIGALRM, handler) | 
 | 364 |             if interrupt is not None: | 
 | 365 |                 signal.siginterrupt(signal.SIGALRM, interrupt) | 
 | 366 |  | 
| Victor Stinner | dfde0d4 | 2011-07-01 15:58:39 +0200 | [diff] [blame] | 367 |             print("ready") | 
 | 368 |             sys.stdout.flush() | 
 | 369 |  | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 370 |             # run the test twice | 
 | 371 |             for loop in range(2): | 
 | 372 |                 # send a SIGALRM in a second (during the read) | 
 | 373 |                 signal.alarm(1) | 
 | 374 |                 try: | 
 | 375 |                     # blocking call: read from a pipe without data | 
 | 376 |                     os.read(r, 1) | 
 | 377 |                 except OSError as err: | 
 | 378 |                     if err.errno != errno.EINTR: | 
 | 379 |                         raise | 
 | 380 |                 else: | 
 | 381 |                     sys.exit(2) | 
 | 382 |             sys.exit(3) | 
 | 383 |         """ % (interrupt,) | 
 | 384 |         with spawn_python('-c', code) as process: | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 385 |             try: | 
| Victor Stinner | 4527365 | 2011-06-22 22:15:51 +0200 | [diff] [blame] | 386 |                 # wait until the child process is loaded and has started | 
 | 387 |                 first_line = process.stdout.readline() | 
 | 388 |  | 
| Victor Stinner | 19e5bcd | 2011-07-01 15:59:54 +0200 | [diff] [blame] | 389 |                 stdout, stderr = process.communicate(timeout=5.0) | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 390 |             except subprocess.TimeoutExpired: | 
 | 391 |                 process.kill() | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 392 |                 return False | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 393 |             else: | 
| Victor Stinner | 4527365 | 2011-06-22 22:15:51 +0200 | [diff] [blame] | 394 |                 stdout = first_line + stdout | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 395 |                 exitcode = process.wait() | 
 | 396 |                 if exitcode not in (2, 3): | 
 | 397 |                     raise Exception("Child error (exit code %s): %s" | 
 | 398 |                                     % (exitcode, stdout)) | 
 | 399 |                 return (exitcode == 3) | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 400 |  | 
 | 401 |     def test_without_siginterrupt(self): | 
| Victor Stinner | 3a7f0f0 | 2011-05-08 02:10:36 +0200 | [diff] [blame] | 402 |         # If a signal handler is installed and siginterrupt is not called | 
 | 403 |         # at all, when that signal arrives, it interrupts a syscall that's in | 
 | 404 |         # progress. | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 405 |         interrupted = self.readpipe_interrupted(None) | 
 | 406 |         self.assertTrue(interrupted) | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 407 |  | 
 | 408 |     def test_siginterrupt_on(self): | 
| Victor Stinner | 3a7f0f0 | 2011-05-08 02:10:36 +0200 | [diff] [blame] | 409 |         # If a signal handler is installed and siginterrupt is called with | 
 | 410 |         # a true value for the second argument, when that signal arrives, it | 
 | 411 |         # interrupts a syscall that's in progress. | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 412 |         interrupted = self.readpipe_interrupted(True) | 
 | 413 |         self.assertTrue(interrupted) | 
| Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 414 |  | 
 | 415 |     def test_siginterrupt_off(self): | 
| Victor Stinner | 3a7f0f0 | 2011-05-08 02:10:36 +0200 | [diff] [blame] | 416 |         # If a signal handler is installed and siginterrupt is called with | 
 | 417 |         # a false value for the second argument, when that signal arrives, it | 
 | 418 |         # does not interrupt a syscall that's in progress. | 
| Victor Stinner | d628496 | 2011-06-20 23:28:09 +0200 | [diff] [blame] | 419 |         interrupted = self.readpipe_interrupted(False) | 
 | 420 |         self.assertFalse(interrupted) | 
| Jean-Paul Calderone | 9c39bc7 | 2010-05-09 03:25:16 +0000 | [diff] [blame] | 421 |  | 
 | 422 |  | 
| Brian Curtin | 3f004b1 | 2010-08-06 19:34:52 +0000 | [diff] [blame] | 423 | @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 424 | class ItimerTest(unittest.TestCase): | 
 | 425 |     def setUp(self): | 
 | 426 |         self.hndl_called = False | 
 | 427 |         self.hndl_count = 0 | 
 | 428 |         self.itimer = None | 
| Christian Heimes | cc47b05 | 2008-03-25 14:56:36 +0000 | [diff] [blame] | 429 |         self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 430 |  | 
 | 431 |     def tearDown(self): | 
| Christian Heimes | cc47b05 | 2008-03-25 14:56:36 +0000 | [diff] [blame] | 432 |         signal.signal(signal.SIGALRM, self.old_alarm) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 433 |         if self.itimer is not None: # test_itimer_exc doesn't change this attr | 
 | 434 |             # just ensure that itimer is stopped | 
 | 435 |             signal.setitimer(self.itimer, 0) | 
 | 436 |  | 
 | 437 |     def sig_alrm(self, *args): | 
 | 438 |         self.hndl_called = True | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 439 |  | 
 | 440 |     def sig_vtalrm(self, *args): | 
 | 441 |         self.hndl_called = True | 
 | 442 |  | 
 | 443 |         if self.hndl_count > 3: | 
 | 444 |             # it shouldn't be here, because it should have been disabled. | 
 | 445 |             raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL " | 
 | 446 |                 "timer.") | 
 | 447 |         elif self.hndl_count == 3: | 
 | 448 |             # disable ITIMER_VIRTUAL, this function shouldn't be called anymore | 
 | 449 |             signal.setitimer(signal.ITIMER_VIRTUAL, 0) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 450 |  | 
 | 451 |         self.hndl_count += 1 | 
 | 452 |  | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 453 |     def sig_prof(self, *args): | 
 | 454 |         self.hndl_called = True | 
 | 455 |         signal.setitimer(signal.ITIMER_PROF, 0) | 
 | 456 |  | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 457 |     def test_itimer_exc(self): | 
 | 458 |         # XXX I'm assuming -1 is an invalid itimer, but maybe some platform | 
 | 459 |         # defines it ? | 
 | 460 |         self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0) | 
| Christian Heimes | cc47b05 | 2008-03-25 14:56:36 +0000 | [diff] [blame] | 461 |         # Negative times are treated as zero on some platforms. | 
 | 462 |         if 0: | 
 | 463 |             self.assertRaises(signal.ItimerError, | 
 | 464 |                               signal.setitimer, signal.ITIMER_REAL, -1) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 465 |  | 
 | 466 |     def test_itimer_real(self): | 
 | 467 |         self.itimer = signal.ITIMER_REAL | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 468 |         signal.setitimer(self.itimer, 1.0) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 469 |         signal.pause() | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 470 |         self.assertEqual(self.hndl_called, True) | 
 | 471 |  | 
| R. David Murray | 44546f8 | 2010-04-21 01:59:28 +0000 | [diff] [blame] | 472 |     # Issue 3864, unknown if this affects earlier versions of freebsd also | 
| Gregory P. Smith | 397cd8a | 2010-10-17 04:23:21 +0000 | [diff] [blame] | 473 |     @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'), | 
 | 474 |         'itimer not reliable (does not mix well with threading) on some BSDs.') | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 475 |     def test_itimer_virtual(self): | 
 | 476 |         self.itimer = signal.ITIMER_VIRTUAL | 
 | 477 |         signal.signal(signal.SIGVTALRM, self.sig_vtalrm) | 
 | 478 |         signal.setitimer(self.itimer, 0.3, 0.2) | 
 | 479 |  | 
| Mark Dickinson | 7837347 | 2009-10-31 10:39:21 +0000 | [diff] [blame] | 480 |         start_time = time.time() | 
| Stefan Krah | f1da97304 | 2010-04-20 08:15:14 +0000 | [diff] [blame] | 481 |         while time.time() - start_time < 60.0: | 
| Mark Dickinson | 9507887 | 2009-10-04 18:47:48 +0000 | [diff] [blame] | 482 |             # use up some virtual time by doing real work | 
 | 483 |             _ = pow(12345, 67890, 10000019) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 484 |             if signal.getitimer(self.itimer) == (0.0, 0.0): | 
 | 485 |                 break # sig_vtalrm handler stopped this itimer | 
| Stefan Krah | f1da97304 | 2010-04-20 08:15:14 +0000 | [diff] [blame] | 486 |         else: # Issue 8424 | 
| Benjamin Peterson | 9b140f6 | 2010-05-15 18:00:56 +0000 | [diff] [blame] | 487 |             self.skipTest("timeout: likely cause: machine too slow or load too " | 
 | 488 |                           "high") | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 489 |  | 
 | 490 |         # virtual itimer should be (0.0, 0.0) now | 
| Ezio Melotti | 19f2aeb | 2010-11-21 01:30:29 +0000 | [diff] [blame] | 491 |         self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0)) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 492 |         # and the handler should have been called | 
| Ezio Melotti | 19f2aeb | 2010-11-21 01:30:29 +0000 | [diff] [blame] | 493 |         self.assertEqual(self.hndl_called, True) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 494 |  | 
| R. David Murray | 44546f8 | 2010-04-21 01:59:28 +0000 | [diff] [blame] | 495 |     # Issue 3864, unknown if this affects earlier versions of freebsd also | 
 | 496 |     @unittest.skipIf(sys.platform=='freebsd6', | 
 | 497 |         'itimer not reliable (does not mix well with threading) on freebsd6') | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 498 |     def test_itimer_prof(self): | 
 | 499 |         self.itimer = signal.ITIMER_PROF | 
 | 500 |         signal.signal(signal.SIGPROF, self.sig_prof) | 
| Neal Norwitz | f5c7c2e | 2008-04-05 04:47:45 +0000 | [diff] [blame] | 501 |         signal.setitimer(self.itimer, 0.2, 0.2) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 502 |  | 
| Mark Dickinson | 7837347 | 2009-10-31 10:39:21 +0000 | [diff] [blame] | 503 |         start_time = time.time() | 
| Stefan Krah | f1da97304 | 2010-04-20 08:15:14 +0000 | [diff] [blame] | 504 |         while time.time() - start_time < 60.0: | 
| Mark Dickinson | 7837347 | 2009-10-31 10:39:21 +0000 | [diff] [blame] | 505 |             # do some work | 
 | 506 |             _ = pow(12345, 67890, 10000019) | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 507 |             if signal.getitimer(self.itimer) == (0.0, 0.0): | 
 | 508 |                 break # sig_prof handler stopped this itimer | 
| Stefan Krah | f1da97304 | 2010-04-20 08:15:14 +0000 | [diff] [blame] | 509 |         else: # Issue 8424 | 
| Benjamin Peterson | 9b140f6 | 2010-05-15 18:00:56 +0000 | [diff] [blame] | 510 |             self.skipTest("timeout: likely cause: machine too slow or load too " | 
 | 511 |                           "high") | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 512 |  | 
| Neal Norwitz | f5c7c2e | 2008-04-05 04:47:45 +0000 | [diff] [blame] | 513 |         # profiling itimer should be (0.0, 0.0) now | 
| Ezio Melotti | 19f2aeb | 2010-11-21 01:30:29 +0000 | [diff] [blame] | 514 |         self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0)) | 
| Neal Norwitz | f5c7c2e | 2008-04-05 04:47:45 +0000 | [diff] [blame] | 515 |         # and the handler should have been called | 
| Martin v. Löwis | 823725e | 2008-03-24 13:39:54 +0000 | [diff] [blame] | 516 |         self.assertEqual(self.hndl_called, True) | 
 | 517 |  | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 518 |  | 
| Victor Stinner | 35b300c | 2011-05-04 13:20:35 +0200 | [diff] [blame] | 519 | class PendingSignalsTests(unittest.TestCase): | 
 | 520 |     """ | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 521 |     Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait() | 
 | 522 |     functions. | 
| Victor Stinner | 35b300c | 2011-05-04 13:20:35 +0200 | [diff] [blame] | 523 |     """ | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 524 |     @unittest.skipUnless(hasattr(signal, 'sigpending'), | 
 | 525 |                          'need signal.sigpending()') | 
 | 526 |     def test_sigpending_empty(self): | 
 | 527 |         self.assertEqual(signal.sigpending(), set()) | 
 | 528 |  | 
 | 529 |     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | 
 | 530 |                          'need signal.pthread_sigmask()') | 
 | 531 |     @unittest.skipUnless(hasattr(signal, 'sigpending'), | 
 | 532 |                          'need signal.sigpending()') | 
 | 533 |     def test_sigpending(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 534 |         code = """if 1: | 
 | 535 |             import os | 
 | 536 |             import signal | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 537 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 538 |             def handler(signum, frame): | 
 | 539 |                 1/0 | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 540 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 541 |             signum = signal.SIGUSR1 | 
 | 542 |             signal.signal(signum, handler) | 
 | 543 |  | 
 | 544 |             signal.pthread_sigmask(signal.SIG_BLOCK, [signum]) | 
 | 545 |             os.kill(os.getpid(), signum) | 
 | 546 |             pending = signal.sigpending() | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 547 |             if pending != {signum}: | 
 | 548 |                 raise Exception('%s != {%s}' % (pending, signum)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 549 |             try: | 
 | 550 |                 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) | 
 | 551 |             except ZeroDivisionError: | 
 | 552 |                 pass | 
 | 553 |             else: | 
 | 554 |                 raise Exception("ZeroDivisionError not raised") | 
 | 555 |         """ | 
 | 556 |         assert_python_ok('-c', code) | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 557 |  | 
 | 558 |     @unittest.skipUnless(hasattr(signal, 'pthread_kill'), | 
 | 559 |                          'need signal.pthread_kill()') | 
 | 560 |     def test_pthread_kill(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 561 |         code = """if 1: | 
 | 562 |             import signal | 
 | 563 |             import threading | 
 | 564 |             import sys | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 565 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 566 |             signum = signal.SIGUSR1 | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 567 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 568 |             def handler(signum, frame): | 
 | 569 |                 1/0 | 
 | 570 |  | 
 | 571 |             signal.signal(signum, handler) | 
 | 572 |  | 
 | 573 |             if sys.platform == 'freebsd6': | 
 | 574 |                 # Issue #12392 and #12469: send a signal to the main thread | 
 | 575 |                 # doesn't work before the creation of the first thread on | 
 | 576 |                 # FreeBSD 6 | 
 | 577 |                 def noop(): | 
 | 578 |                     pass | 
 | 579 |                 thread = threading.Thread(target=noop) | 
 | 580 |                 thread.start() | 
 | 581 |                 thread.join() | 
 | 582 |  | 
 | 583 |             tid = threading.get_ident() | 
 | 584 |             try: | 
 | 585 |                 signal.pthread_kill(tid, signum) | 
 | 586 |             except ZeroDivisionError: | 
 | 587 |                 pass | 
 | 588 |             else: | 
 | 589 |                 raise Exception("ZeroDivisionError not raised") | 
 | 590 |         """ | 
 | 591 |         assert_python_ok('-c', code) | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 592 |  | 
| Victor Stinner | 7f294d1 | 2011-06-10 14:02:10 +0200 | [diff] [blame] | 593 |     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | 
 | 594 |                          'need signal.pthread_sigmask()') | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 595 |     def wait_helper(self, blocked, test): | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 596 |         """ | 
 | 597 |         test: body of the "def test(signum):" function. | 
 | 598 |         blocked: number of the blocked signal | 
 | 599 |         """ | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 600 |         code = '''if 1: | 
 | 601 |         import signal | 
 | 602 |         import sys | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 603 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 604 |         def handler(signum, frame): | 
 | 605 |             1/0 | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 606 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 607 |         %s | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 608 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 609 |         blocked = %s | 
 | 610 |         signum = signal.SIGALRM | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 611 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 612 |         # child: block and wait the signal | 
 | 613 |         try: | 
 | 614 |             signal.signal(signum, handler) | 
 | 615 |             signal.pthread_sigmask(signal.SIG_BLOCK, [blocked]) | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 616 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 617 |             # Do the tests | 
 | 618 |             test(signum) | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 619 |  | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 620 |             # The handler must not be called on unblock | 
 | 621 |             try: | 
 | 622 |                 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked]) | 
 | 623 |             except ZeroDivisionError: | 
 | 624 |                 print("the signal handler has been called", | 
 | 625 |                       file=sys.stderr) | 
 | 626 |                 sys.exit(1) | 
 | 627 |         except BaseException as err: | 
 | 628 |             print("error: {}".format(err), file=sys.stderr) | 
 | 629 |             sys.stderr.flush() | 
 | 630 |             sys.exit(1) | 
 | 631 |         ''' % (test.strip(), blocked) | 
| Victor Stinner | 415007e | 2011-06-13 16:19:06 +0200 | [diff] [blame] | 632 |  | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 633 |         # sig*wait* must be called with the signal blocked: since the current | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 634 |         # process might have several threads running, use a subprocess to have | 
 | 635 |         # a single thread. | 
 | 636 |         assert_python_ok('-c', code) | 
| Victor Stinner | af49460 | 2011-06-10 12:48:13 +0200 | [diff] [blame] | 637 |  | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 638 |     @unittest.skipUnless(hasattr(signal, 'sigwait'), | 
 | 639 |                          'need signal.sigwait()') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 640 |     def test_sigwait(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 641 |         self.wait_helper(signal.SIGALRM, ''' | 
 | 642 |         def test(signum): | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 643 |             signal.alarm(1) | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 644 |             received = signal.sigwait([signum]) | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 645 |             if received != signum: | 
 | 646 |                 raise Exception('received %s, not %s' % (received, signum)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 647 |         ''') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 648 |  | 
 | 649 |     @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'), | 
 | 650 |                          'need signal.sigwaitinfo()') | 
 | 651 |     def test_sigwaitinfo(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 652 |         self.wait_helper(signal.SIGALRM, ''' | 
 | 653 |         def test(signum): | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 654 |             signal.alarm(1) | 
 | 655 |             info = signal.sigwaitinfo([signum]) | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 656 |             if info.si_signo != signum: | 
 | 657 |                 raise Exception("info.si_signo != %s" % signum) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 658 |         ''') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 659 |  | 
 | 660 |     @unittest.skipUnless(hasattr(signal, 'sigtimedwait'), | 
 | 661 |                          'need signal.sigtimedwait()') | 
 | 662 |     def test_sigtimedwait(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 663 |         self.wait_helper(signal.SIGALRM, ''' | 
 | 664 |         def test(signum): | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 665 |             signal.alarm(1) | 
 | 666 |             info = signal.sigtimedwait([signum], (10, 1000)) | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 667 |             if info.si_signo != signum: | 
 | 668 |                 raise Exception('info.si_signo != %s' % signum) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 669 |         ''') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 670 |  | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 671 |     @unittest.skipUnless(hasattr(signal, 'sigtimedwait'), | 
 | 672 |                          'need signal.sigtimedwait()') | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 673 |     # issue #12303: sigtimedwait() takes 30 seconds on FreeBSD 6 (kernel bug) | 
 | 674 |     @unittest.skipIf(sys.platform =='freebsd6', | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 675 |         "sigtimedwait() with a null timeout doens't work on FreeBSD 6") | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 676 |     def test_sigtimedwait_poll(self): | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 677 |         # check that polling with sigtimedwait works | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 678 |         self.wait_helper(signal.SIGALRM, ''' | 
 | 679 |         def test(signum): | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 680 |             import os | 
 | 681 |             os.kill(os.getpid(), signum) | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 682 |             info = signal.sigtimedwait([signum], (0, 0)) | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 683 |             if info.si_signo != signum: | 
 | 684 |                 raise Exception('info.si_signo != %s' % signum) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 685 |         ''') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 686 |  | 
 | 687 |     @unittest.skipUnless(hasattr(signal, 'sigtimedwait'), | 
 | 688 |                          'need signal.sigtimedwait()') | 
 | 689 |     def test_sigtimedwait_timeout(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 690 |         self.wait_helper(signal.SIGALRM, ''' | 
 | 691 |         def test(signum): | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 692 |             received = signal.sigtimedwait([signum], (1, 0)) | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 693 |             if received is not None: | 
 | 694 |                 raise Exception("received=%r" % (received,)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 695 |         ''') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 696 |  | 
 | 697 |     @unittest.skipUnless(hasattr(signal, 'sigtimedwait'), | 
 | 698 |                          'need signal.sigtimedwait()') | 
 | 699 |     def test_sigtimedwait_negative_timeout(self): | 
 | 700 |         signum = signal.SIGALRM | 
 | 701 |         self.assertRaises(ValueError, signal.sigtimedwait, [signum], (-1, -1)) | 
 | 702 |         self.assertRaises(ValueError, signal.sigtimedwait, [signum], (0, -1)) | 
 | 703 |         self.assertRaises(ValueError, signal.sigtimedwait, [signum], (-1, 0)) | 
 | 704 |  | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 705 |     @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'), | 
 | 706 |                          'need signal.sigwaitinfo()') | 
 | 707 |     def test_sigwaitinfo_interrupted(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 708 |         self.wait_helper(signal.SIGUSR1, ''' | 
 | 709 |         def test(signum): | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 710 |             import errno | 
 | 711 |  | 
 | 712 |             hndl_called = True | 
 | 713 |             def alarm_handler(signum, frame): | 
 | 714 |                 hndl_called = False | 
 | 715 |  | 
 | 716 |             signal.signal(signal.SIGALRM, alarm_handler) | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 717 |             signal.alarm(1) | 
 | 718 |             try: | 
 | 719 |                 signal.sigwaitinfo([signal.SIGUSR1]) | 
 | 720 |             except OSError as e: | 
 | 721 |                 if e.errno == errno.EINTR: | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 722 |                     if not hndl_called: | 
 | 723 |                         raise Exception("SIGALRM handler not called") | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 724 |                 else: | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 725 |                     raise Exception("Expected EINTR to be raised by sigwaitinfo") | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 726 |             else: | 
| Victor Stinner | 9e8b82f | 2011-06-29 10:43:02 +0200 | [diff] [blame] | 727 |                 raise Exception("Expected EINTR to be raised by sigwaitinfo") | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 728 |         ''') | 
| Ross Lagerwall | bc80822 | 2011-06-25 12:13:40 +0200 | [diff] [blame] | 729 |  | 
 | 730 |     @unittest.skipUnless(hasattr(signal, 'sigwait'), | 
 | 731 |                          'need signal.sigwait()') | 
| Victor Stinner | 415007e | 2011-06-13 16:19:06 +0200 | [diff] [blame] | 732 |     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | 
 | 733 |                          'need signal.pthread_sigmask()') | 
| Victor Stinner | 10c30d6 | 2011-06-10 01:39:53 +0200 | [diff] [blame] | 734 |     @unittest.skipIf(threading is None, "test needs threading module") | 
 | 735 |     def test_sigwait_thread(self): | 
| Victor Stinner | 415007e | 2011-06-13 16:19:06 +0200 | [diff] [blame] | 736 |         # Check that calling sigwait() from a thread doesn't suspend the whole | 
 | 737 |         # process. A new interpreter is spawned to avoid problems when mixing | 
 | 738 |         # threads and fork(): only async-safe functions are allowed between | 
 | 739 |         # fork() and exec(). | 
 | 740 |         assert_python_ok("-c", """if True: | 
 | 741 |             import os, threading, sys, time, signal | 
| Victor Stinner | 10c30d6 | 2011-06-10 01:39:53 +0200 | [diff] [blame] | 742 |  | 
| Victor Stinner | 415007e | 2011-06-13 16:19:06 +0200 | [diff] [blame] | 743 |             # the default handler terminates the process | 
 | 744 |             signum = signal.SIGUSR1 | 
 | 745 |  | 
 | 746 |             def kill_later(): | 
 | 747 |                 # wait until the main thread is waiting in sigwait() | 
 | 748 |                 time.sleep(1) | 
 | 749 |                 os.kill(os.getpid(), signum) | 
 | 750 |  | 
 | 751 |             # the signal must be blocked by all the threads | 
 | 752 |             signal.pthread_sigmask(signal.SIG_BLOCK, [signum]) | 
 | 753 |             killer = threading.Thread(target=kill_later) | 
| Victor Stinner | af49460 | 2011-06-10 12:48:13 +0200 | [diff] [blame] | 754 |             killer.start() | 
 | 755 |             received = signal.sigwait([signum]) | 
 | 756 |             if received != signum: | 
 | 757 |                 print("sigwait() received %s, not %s" % (received, signum), | 
 | 758 |                       file=sys.stderr) | 
| Victor Stinner | 415007e | 2011-06-13 16:19:06 +0200 | [diff] [blame] | 759 |                 sys.exit(1) | 
| Victor Stinner | 10c30d6 | 2011-06-10 01:39:53 +0200 | [diff] [blame] | 760 |             killer.join() | 
| Victor Stinner | 415007e | 2011-06-13 16:19:06 +0200 | [diff] [blame] | 761 |             # unblock the signal, which should have been cleared by sigwait() | 
 | 762 |             signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) | 
 | 763 |         """) | 
| Victor Stinner | af49460 | 2011-06-10 12:48:13 +0200 | [diff] [blame] | 764 |  | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 765 |     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | 
 | 766 |                          'need signal.pthread_sigmask()') | 
 | 767 |     def test_pthread_sigmask_arguments(self): | 
 | 768 |         self.assertRaises(TypeError, signal.pthread_sigmask) | 
 | 769 |         self.assertRaises(TypeError, signal.pthread_sigmask, 1) | 
 | 770 |         self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3) | 
 | 771 |         self.assertRaises(OSError, signal.pthread_sigmask, 1700, []) | 
 | 772 |  | 
 | 773 |     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | 
 | 774 |                          'need signal.pthread_sigmask()') | 
 | 775 |     def test_pthread_sigmask(self): | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 776 |         code = """if 1: | 
 | 777 |         import signal | 
 | 778 |         import os; import threading | 
 | 779 |  | 
 | 780 |         def handler(signum, frame): | 
 | 781 |             1/0 | 
 | 782 |  | 
 | 783 |         def kill(signum): | 
 | 784 |             os.kill(os.getpid(), signum) | 
 | 785 |  | 
 | 786 |         def read_sigmask(): | 
 | 787 |             return signal.pthread_sigmask(signal.SIG_BLOCK, []) | 
 | 788 |  | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 789 |         signum = signal.SIGUSR1 | 
| Victor Stinner | 6fd49e1 | 2011-05-04 12:38:03 +0200 | [diff] [blame] | 790 |  | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 791 |         # Install our signal handler | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 792 |         old_handler = signal.signal(signum, handler) | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 793 |  | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 794 |         # Unblock SIGUSR1 (and copy the old mask) to test our signal handler | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 795 |         old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 796 |         try: | 
 | 797 |             kill(signum) | 
 | 798 |         except ZeroDivisionError: | 
 | 799 |             pass | 
 | 800 |         else: | 
 | 801 |             raise Exception("ZeroDivisionError not raised") | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 802 |  | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 803 |         # Block and then raise SIGUSR1. The signal is blocked: the signal | 
 | 804 |         # handler is not called, and the signal is now pending | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 805 |         signal.pthread_sigmask(signal.SIG_BLOCK, [signum]) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 806 |         kill(signum) | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 807 |  | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 808 |         # Check the new mask | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 809 |         blocked = read_sigmask() | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 810 |         if signum not in blocked: | 
 | 811 |             raise Exception("%s not in %s" % (signum, blocked)) | 
 | 812 |         if old_mask ^ blocked != {signum}: | 
 | 813 |             raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum)) | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 814 |  | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 815 |         # Unblock SIGUSR1 | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 816 |         try: | 
 | 817 |             # unblock the pending signal calls immediatly the signal handler | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 818 |             signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 819 |         except ZeroDivisionError: | 
 | 820 |             pass | 
 | 821 |         else: | 
 | 822 |             raise Exception("ZeroDivisionError not raised") | 
 | 823 |         try: | 
 | 824 |             kill(signum) | 
 | 825 |         except ZeroDivisionError: | 
 | 826 |             pass | 
 | 827 |         else: | 
 | 828 |             raise Exception("ZeroDivisionError not raised") | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 829 |  | 
| Victor Stinner | d0e516d | 2011-05-03 14:57:12 +0200 | [diff] [blame] | 830 |         # Check the new mask | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 831 |         unblocked = read_sigmask() | 
| Victor Stinner | 0a01f13 | 2011-07-04 18:06:35 +0200 | [diff] [blame^] | 832 |         if signum in unblocked: | 
 | 833 |             raise Exception("%s in %s" % (signum, unblocked)) | 
 | 834 |         if blocked ^ unblocked != {signum}: | 
 | 835 |             raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum)) | 
 | 836 |         if old_mask != unblocked: | 
 | 837 |             raise Exception("%s != %s" % (old_mask, unblocked)) | 
| Victor Stinner | d554cdf | 2011-07-04 17:49:40 +0200 | [diff] [blame] | 838 |         """ | 
 | 839 |         assert_python_ok('-c', code) | 
 | 840 |  | 
 | 841 |     @unittest.skipIf(sys.platform == 'freebsd6', | 
 | 842 |         "issue #12392: send a signal to the main thread doesn't work " | 
 | 843 |         "before the creation of the first thread on FreeBSD 6") | 
 | 844 |     @unittest.skipUnless(hasattr(signal, 'pthread_kill'), | 
 | 845 |                          'need signal.pthread_kill()') | 
 | 846 |     def test_pthread_kill_main_thread(self): | 
 | 847 |         # Test that a signal can be sent to the main thread with pthread_kill() | 
 | 848 |         # before any other thread has been created (see issue #12392). | 
 | 849 |         code = """if True: | 
 | 850 |             import threading | 
 | 851 |             import signal | 
 | 852 |             import sys | 
 | 853 |  | 
 | 854 |             def handler(signum, frame): | 
 | 855 |                 sys.exit(3) | 
 | 856 |  | 
 | 857 |             signal.signal(signal.SIGUSR1, handler) | 
 | 858 |             signal.pthread_kill(threading.get_ident(), signal.SIGUSR1) | 
 | 859 |             sys.exit(2) | 
 | 860 |         """ | 
 | 861 |  | 
 | 862 |         with spawn_python('-c', code) as process: | 
 | 863 |             stdout, stderr = process.communicate() | 
 | 864 |             exitcode = process.wait() | 
 | 865 |             if exitcode != 3: | 
 | 866 |                 raise Exception("Child error (exit code %s): %s" % | 
 | 867 |                                 (exitcode, stdout)) | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 868 |  | 
 | 869 |  | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 870 | def test_main(): | 
| Antoine Pitrou | 8189ab8 | 2011-03-20 17:35:32 +0100 | [diff] [blame] | 871 |     try: | 
| Victor Stinner | b3e7219 | 2011-05-08 01:46:11 +0200 | [diff] [blame] | 872 |         support.run_unittest(PosixTests, InterProcessSignalTests, | 
| Antoine Pitrou | 8189ab8 | 2011-03-20 17:35:32 +0100 | [diff] [blame] | 873 |                              WakeupSignalTests, SiginterruptTest, | 
| Victor Stinner | a929335 | 2011-04-30 15:21:58 +0200 | [diff] [blame] | 874 |                              ItimerTest, WindowsSignalTests, | 
| Victor Stinner | 35b300c | 2011-05-04 13:20:35 +0200 | [diff] [blame] | 875 |                              PendingSignalsTests) | 
| Antoine Pitrou | 8189ab8 | 2011-03-20 17:35:32 +0100 | [diff] [blame] | 876 |     finally: | 
 | 877 |         support.reap_children() | 
| Thomas Wouters | ed03b41 | 2007-08-28 21:37:11 +0000 | [diff] [blame] | 878 |  | 
 | 879 |  | 
 | 880 | if __name__ == "__main__": | 
 | 881 |     test_main() |