blob: ebdd3bcd76b41f551551c9c8cbef93a512edbd39 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002from test import support
Raymond Hettinger722d8c32009-06-18 22:21:03 +00003from contextlib import closing
Christian Heimescc47b052008-03-25 14:56:36 +00004import gc
Christian Heimes4fbc72b2008-03-22 00:47:35 +00005import pickle
6import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00007import signal
Victor Stinnerd49b1f12011-05-08 02:03:15 +02008import struct
Christian Heimes4fbc72b2008-03-22 00:47:35 +00009import subprocess
10import traceback
Christian Heimesc06950e2008-02-28 21:17:00 +000011import sys, os, time, errno
Victor Stinnerd6284962011-06-20 23:28:09 +020012from test.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020013try:
14 import threading
15except ImportError:
16 threading = None
Christian Heimesc06950e2008-02-28 21:17:00 +000017
Brian Curtin912443c2010-09-06 16:10:04 +000018if sys.platform in ('os2', 'riscos'):
19 raise unittest.SkipTest("Can't test signal on %s" % sys.platform)
Christian Heimesc06950e2008-02-28 21:17:00 +000020
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000021
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000022class HandlerBCalled(Exception):
23 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000024
Christian Heimes4fbc72b2008-03-22 00:47:35 +000025
26def 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 Petersonad9d48d2008-04-02 21:49:44 +000036def ignoring_eintr(__func, *args, **kwargs):
37 try:
38 return __func(*args, **kwargs)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000039 except EnvironmentError as e:
40 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000041 raise
42 return None
43
44
Brian Curtin3f004b12010-08-06 19:34:52 +000045@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000046class InterProcessSignalTests(unittest.TestCase):
47 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000048
Christian Heimescc47b052008-03-25 14:56:36 +000049 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 Heimes5e696852008-04-09 08:37:03 +000057 def format_frame(self, frame, limit=None):
58 return ''.join(traceback.format_stack(frame, limit=limit))
59
60 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000061 self.a_called = True
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000062
Christian Heimes5e696852008-04-09 08:37:03 +000063 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000064 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000065 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000066
Christian Heimes4fbc72b2008-03-22 00:47:35 +000067 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 Drake004d5e62000-10-23 17:22:08 +000076
Christian Heimes4fbc72b2008-03-22 00:47:35 +000077 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. Hudson5c26e862004-06-11 18:09:28 +000084
Christian Heimes4fbc72b2008-03-22 00:47:35 +000085 # Variables the signals will modify:
86 self.a_called = False
87 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088
Christian Heimes4fbc72b2008-03-22 00:47:35 +000089 # Let the sub-processes know who to send signals to.
90 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000091
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000092 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 Heimes4fbc72b2008-03-22 00:47:35 +000097 self.assertTrue(self.a_called)
98 self.assertFalse(self.b_called)
99 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000100
Christian Heimes5e696852008-04-09 08:37:03 +0000101 # 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 Woutersed03b412007-08-28 21:37:11 +0000105 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000106 child = subprocess.Popen(['kill', '-USR1', str(pid)])
107 # This wait should be interrupted by the signal's exception.
108 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000109 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000110 self.fail('HandlerBCalled exception not thrown')
111 except HandlerBCalled:
112 self.assertTrue(self.b_called)
113 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000115 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
116 if child:
117 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000118
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 Petersonad9d48d2008-04-02 21:49:44 +0000125 # But if another signal arrives before the alarm, pause
126 # may return early.
127 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000128 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200129 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000130 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000131 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000132 traceback.format_exc())
133 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000134 self.fail("pause returned of its own accord, and the signal"
135 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
R. David Murray44546f82010-04-21 01:59:28 +0000137 # 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 Heimes4fbc72b2008-03-22 00:47:35 +0000141 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 Hettinger686057b2009-06-04 00:11:54 +0000148 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
149 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000150 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 Woutersed03b412007-08-28 21:37:11 +0000182
183
Brian Curtin3f004b12010-08-06 19:34:52 +0000184@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200185class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000186 def trivial_signal_handler(self, *args):
187 pass
188
Thomas Woutersed03b412007-08-28 21:37:11 +0000189 def test_out_of_range_signal_number_raises_error(self):
190 self.assertRaises(ValueError, signal.getsignal, 4242)
191
Thomas Woutersed03b412007-08-28 21:37:11 +0000192 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000193 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000194
195 def test_setting_signal_handler_to_none_raises_error(self):
196 self.assertRaises(TypeError, signal.signal,
197 signal.SIGUSR1, None)
198
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000199 def test_getsignal(self):
200 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000201 self.assertEqual(signal.getsignal(signal.SIGHUP),
202 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000203 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000204 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000205
206
Brian Curtin3f004b12010-08-06 19:34:52 +0000207@unittest.skipUnless(sys.platform == "win32", "Windows specific")
208class WindowsSignalTests(unittest.TestCase):
209 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000210 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000211 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +0000212 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 Curtin3f004b12010-08-06 19:34:52 +0000217
218 with self.assertRaises(ValueError):
219 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000220
221 with self.assertRaises(ValueError):
222 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000223
224
225@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000226class WakeupSignalTests(unittest.TestCase):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200227 def check_wakeup(self, test_body, *signals):
228 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200229 code = """if 1:
230 import fcntl
231 import os
232 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200233 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000234
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200235 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200236
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200237 def handler(signum, frame):
238 pass
239
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200240 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 Stinner0a01f132011-07-04 18:06:35 +0200247 if raised != signals:
248 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200249
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200250 {}
251
252 signal.signal(signal.SIGALRM, handler)
253 read, write = os.pipe()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200254 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 Stinnere40b3aa2011-07-04 17:35:10 +0200258 signal.set_wakeup_fd(write)
259
260 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200261 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200262
263 os.close(read)
264 os.close(write)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200265 """.format(signals, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200266
267 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200268
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000269 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200270 self.check_wakeup("""def test():
271 import select
272 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000273
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200274 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 Stinner0a01f132011-07-04 18:06:35 +0200284 if dt >= TIMEOUT_HALF:
285 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200286 select.select([read], [], [], TIMEOUT_FULL)
287 after_time = time.time()
288 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200289 if dt >= TIMEOUT_HALF:
290 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200291 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000292
293 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200294 self.check_wakeup("""def test():
295 import select
296 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000297
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200298 TIMEOUT_FULL = 10
299 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000300
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200301 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 Stinner0a01f132011-07-04 18:06:35 +0200312 if dt >= TIMEOUT_HALF:
313 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200314 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200315
316 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200317 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 Heimes5fb7c2a2007-12-24 08:52:31 +0000322
Victor Stinnerc13ef662011-05-25 02:35:58 +0200323 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
324 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200325 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200326 self.check_wakeup("""def test():
327 signum1 = signal.SIGUSR1
328 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200329
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200330 signal.signal(signum1, handler)
331 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200332
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200333 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 Stinnerc13ef662011-05-25 02:35:58 +0200339
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000340
Brian Curtin3f004b12010-08-06 19:34:52 +0000341@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000342class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000343
Victor Stinnerd6284962011-06-20 23:28:09 +0200344 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000345 """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 Stinnerd6284962011-06-20 23:28:09 +0200349 # 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 Calderone9c39bc72010-05-09 03:25:16 +0000356
Victor Stinnerd6284962011-06-20 23:28:09 +0200357 interrupt = %r
358 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000359
Victor Stinnerd6284962011-06-20 23:28:09 +0200360 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 Stinnerdfde0d42011-07-01 15:58:39 +0200367 print("ready")
368 sys.stdout.flush()
369
Victor Stinnerd6284962011-06-20 23:28:09 +0200370 # 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 Heimes8640e742008-02-23 16:23:06 +0000385 try:
Victor Stinner45273652011-06-22 22:15:51 +0200386 # wait until the child process is loaded and has started
387 first_line = process.stdout.readline()
388
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200389 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200390 except subprocess.TimeoutExpired:
391 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000392 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200393 else:
Victor Stinner45273652011-06-22 22:15:51 +0200394 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200395 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 Heimes8640e742008-02-23 16:23:06 +0000400
401 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200402 # 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 Stinnerd6284962011-06-20 23:28:09 +0200405 interrupted = self.readpipe_interrupted(None)
406 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000407
408 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200409 # 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 Stinnerd6284962011-06-20 23:28:09 +0200412 interrupted = self.readpipe_interrupted(True)
413 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000414
415 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200416 # 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 Stinnerd6284962011-06-20 23:28:09 +0200419 interrupted = self.readpipe_interrupted(False)
420 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000421
422
Brian Curtin3f004b12010-08-06 19:34:52 +0000423@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000424class ItimerTest(unittest.TestCase):
425 def setUp(self):
426 self.hndl_called = False
427 self.hndl_count = 0
428 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000429 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000430
431 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000432 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000433 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öwis823725e2008-03-24 13:39:54 +0000439
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öwis823725e2008-03-24 13:39:54 +0000450
451 self.hndl_count += 1
452
Martin v. Löwis823725e2008-03-24 13:39:54 +0000453 def sig_prof(self, *args):
454 self.hndl_called = True
455 signal.setitimer(signal.ITIMER_PROF, 0)
456
Martin v. Löwis823725e2008-03-24 13:39:54 +0000457 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 Heimescc47b052008-03-25 14:56:36 +0000461 # 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öwis823725e2008-03-24 13:39:54 +0000465
466 def test_itimer_real(self):
467 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000468 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000469 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000470 self.assertEqual(self.hndl_called, True)
471
R. David Murray44546f82010-04-21 01:59:28 +0000472 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000473 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
474 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000475 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 Dickinson78373472009-10-31 10:39:21 +0000480 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000481 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000482 # use up some virtual time by doing real work
483 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000484 if signal.getitimer(self.itimer) == (0.0, 0.0):
485 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000486 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000487 self.skipTest("timeout: likely cause: machine too slow or load too "
488 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000489
490 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000491 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000492 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000493 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000494
R. David Murray44546f82010-04-21 01:59:28 +0000495 # 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öwis823725e2008-03-24 13:39:54 +0000498 def test_itimer_prof(self):
499 self.itimer = signal.ITIMER_PROF
500 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000501 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000502
Mark Dickinson78373472009-10-31 10:39:21 +0000503 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000504 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000505 # do some work
506 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000507 if signal.getitimer(self.itimer) == (0.0, 0.0):
508 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000509 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000510 self.skipTest("timeout: likely cause: machine too slow or load too "
511 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000512
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000513 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000514 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000515 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000516 self.assertEqual(self.hndl_called, True)
517
Victor Stinnera9293352011-04-30 15:21:58 +0200518
Victor Stinner35b300c2011-05-04 13:20:35 +0200519class PendingSignalsTests(unittest.TestCase):
520 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200521 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
522 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200523 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200524 @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 Stinnerd554cdf2011-07-04 17:49:40 +0200534 code = """if 1:
535 import os
536 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200537
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200538 def handler(signum, frame):
539 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200540
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200541 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 Stinner0a01f132011-07-04 18:06:35 +0200547 if pending != {signum}:
548 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200549 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 Stinnerb3e72192011-05-08 01:46:11 +0200557
558 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
559 'need signal.pthread_kill()')
560 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200561 code = """if 1:
562 import signal
563 import threading
564 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200565
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200566 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200567
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200568 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 Stinnerb3e72192011-05-08 01:46:11 +0200592
Victor Stinner7f294d12011-06-10 14:02:10 +0200593 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
594 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200595 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200596 """
597 test: body of the "def test(signum):" function.
598 blocked: number of the blocked signal
599 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200600 code = '''if 1:
601 import signal
602 import sys
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200603
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200604 def handler(signum, frame):
605 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200606
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200607 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200608
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200609 blocked = %s
610 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200611
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200612 # child: block and wait the signal
613 try:
614 signal.signal(signum, handler)
615 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200616
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200617 # Do the tests
618 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200619
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200620 # 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 Stinner415007e2011-06-13 16:19:06 +0200632
Ross Lagerwallbc808222011-06-25 12:13:40 +0200633 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200634 # process might have several threads running, use a subprocess to have
635 # a single thread.
636 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200637
Victor Stinnerb3e72192011-05-08 01:46:11 +0200638 @unittest.skipUnless(hasattr(signal, 'sigwait'),
639 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200640 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200641 self.wait_helper(signal.SIGALRM, '''
642 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200643 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200644 received = signal.sigwait([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200645 if received != signum:
646 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200647 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200648
649 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
650 'need signal.sigwaitinfo()')
651 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200652 self.wait_helper(signal.SIGALRM, '''
653 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200654 signal.alarm(1)
655 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200656 if info.si_signo != signum:
657 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200658 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200659
660 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
661 'need signal.sigtimedwait()')
662 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200663 self.wait_helper(signal.SIGALRM, '''
664 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200665 signal.alarm(1)
666 info = signal.sigtimedwait([signum], (10, 1000))
Victor Stinner0a01f132011-07-04 18:06:35 +0200667 if info.si_signo != signum:
668 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200669 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200670
Ross Lagerwallbc808222011-06-25 12:13:40 +0200671 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
672 'need signal.sigtimedwait()')
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200673 # issue #12303: sigtimedwait() takes 30 seconds on FreeBSD 6 (kernel bug)
674 @unittest.skipIf(sys.platform =='freebsd6',
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200675 "sigtimedwait() with a null timeout doens't work on FreeBSD 6")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200676 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200677 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200678 self.wait_helper(signal.SIGALRM, '''
679 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200680 import os
681 os.kill(os.getpid(), signum)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200682 info = signal.sigtimedwait([signum], (0, 0))
Victor Stinner0a01f132011-07-04 18:06:35 +0200683 if info.si_signo != signum:
684 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200685 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200686
687 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
688 'need signal.sigtimedwait()')
689 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200690 self.wait_helper(signal.SIGALRM, '''
691 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200692 received = signal.sigtimedwait([signum], (1, 0))
Victor Stinner0a01f132011-07-04 18:06:35 +0200693 if received is not None:
694 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200695 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200696
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 Lagerwallbc808222011-06-25 12:13:40 +0200705 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
706 'need signal.sigwaitinfo()')
707 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200708 self.wait_helper(signal.SIGUSR1, '''
709 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200710 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 Lagerwallbc808222011-06-25 12:13:40 +0200717 signal.alarm(1)
718 try:
719 signal.sigwaitinfo([signal.SIGUSR1])
720 except OSError as e:
721 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200722 if not hndl_called:
723 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200724 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200725 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200726 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200727 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200728 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200729
730 @unittest.skipUnless(hasattr(signal, 'sigwait'),
731 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200732 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
733 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200734 @unittest.skipIf(threading is None, "test needs threading module")
735 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200736 # 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 Stinner10c30d62011-06-10 01:39:53 +0200742
Victor Stinner415007e2011-06-13 16:19:06 +0200743 # 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 Stinneraf494602011-06-10 12:48:13 +0200754 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 Stinner415007e2011-06-13 16:19:06 +0200759 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200760 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200761 # unblock the signal, which should have been cleared by sigwait()
762 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
763 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200764
Victor Stinnerb3e72192011-05-08 01:46:11 +0200765 @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 Stinnerd554cdf2011-07-04 17:49:40 +0200776 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 Stinnerb3e72192011-05-08 01:46:11 +0200789 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200790
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200791 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200792 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200793
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200794 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200795 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200796 try:
797 kill(signum)
798 except ZeroDivisionError:
799 pass
800 else:
801 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200802
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200803 # Block and then raise SIGUSR1. The signal is blocked: the signal
804 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200805 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200806 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200807
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200808 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200809 blocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200810 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 Stinnera9293352011-04-30 15:21:58 +0200814
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200815 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200816 try:
817 # unblock the pending signal calls immediatly the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200818 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200819 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 Stinnera9293352011-04-30 15:21:58 +0200829
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200830 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200831 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200832 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 Stinnerd554cdf2011-07-04 17:49:40 +0200838 """
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 Stinnera9293352011-04-30 15:21:58 +0200868
869
Thomas Woutersed03b412007-08-28 21:37:11 +0000870def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100871 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200872 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100873 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200874 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200875 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100876 finally:
877 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000878
879
880if __name__ == "__main__":
881 test_main()