blob: 3d250e134bfb1e83a4aad0b11387f04356a83350 [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
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000018
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000019class HandlerBCalled(Exception):
20 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000021
Christian Heimes4fbc72b2008-03-22 00:47:35 +000022
23def exit_subprocess():
24 """Use os._exit(0) to exit the current subprocess.
25
26 Otherwise, the test catches the SystemExit and continues executing
27 in parallel with the original test, so you wind up with an
28 exponential number of tests running concurrently.
29 """
30 os._exit(0)
31
32
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000033def ignoring_eintr(__func, *args, **kwargs):
34 try:
35 return __func(*args, **kwargs)
Andrew Svetlov3438fa42012-12-17 23:35:18 +020036 except OSError as e:
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000037 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000038 raise
39 return None
40
41
Brian Curtin3f004b12010-08-06 19:34:52 +000042@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000043class InterProcessSignalTests(unittest.TestCase):
44 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000045
Christian Heimescc47b052008-03-25 14:56:36 +000046 def setUp(self):
47 self.using_gc = gc.isenabled()
48 gc.disable()
49
50 def tearDown(self):
51 if self.using_gc:
52 gc.enable()
53
Christian Heimes5e696852008-04-09 08:37:03 +000054 def format_frame(self, frame, limit=None):
55 return ''.join(traceback.format_stack(frame, limit=limit))
56
57 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000058 self.a_called = True
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000059
Christian Heimes5e696852008-04-09 08:37:03 +000060 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000061 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000062 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000063
Christian Heimes4fbc72b2008-03-22 00:47:35 +000064 def wait(self, child):
65 """Wait for child to finish, ignoring EINTR."""
66 while True:
67 try:
68 child.wait()
69 return
70 except OSError as e:
71 if e.errno != errno.EINTR:
72 raise
Fred Drake004d5e62000-10-23 17:22:08 +000073
Christian Heimes4fbc72b2008-03-22 00:47:35 +000074 def run_test(self):
75 # Install handlers. This function runs in a sub-process, so we
76 # don't worry about re-setting the default handlers.
77 signal.signal(signal.SIGHUP, self.handlerA)
78 signal.signal(signal.SIGUSR1, self.handlerB)
79 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
80 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000081
Christian Heimes4fbc72b2008-03-22 00:47:35 +000082 # Variables the signals will modify:
83 self.a_called = False
84 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000085
Christian Heimes4fbc72b2008-03-22 00:47:35 +000086 # Let the sub-processes know who to send signals to.
87 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000089 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
90 if child:
91 self.wait(child)
92 if not self.a_called:
93 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +000094 self.assertTrue(self.a_called)
95 self.assertFalse(self.b_called)
96 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000097
Christian Heimes5e696852008-04-09 08:37:03 +000098 # Make sure the signal isn't delivered while the previous
99 # Popen object is being destroyed, because __del__ swallows
100 # exceptions.
101 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000102 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000103 child = subprocess.Popen(['kill', '-USR1', str(pid)])
104 # This wait should be interrupted by the signal's exception.
105 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000106 time.sleep(1) # Give the signal time to be delivered.
Andrew Svetlov737fb892012-12-18 21:14:22 +0200107 self.fail('HandlerBCalled exception not raised')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000108 except HandlerBCalled:
109 self.assertTrue(self.b_called)
110 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000112 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
113 if child:
114 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000115
116 try:
117 signal.alarm(1)
118 # The race condition in pause doesn't matter in this case,
119 # since alarm is going to raise a KeyboardException, which
120 # will skip the call.
121 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000122 # But if another signal arrives before the alarm, pause
123 # may return early.
124 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000125 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200126 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000127 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000128 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000129 traceback.format_exc())
130 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000131 self.fail("pause returned of its own accord, and the signal"
132 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000133
R. David Murray44546f82010-04-21 01:59:28 +0000134 # Issue 3864, unknown if this affects earlier versions of freebsd also
135 @unittest.skipIf(sys.platform=='freebsd6',
136 'inter process signals not reliable (do not mix well with threading) '
137 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000138 def test_main(self):
139 # This function spawns a child process to insulate the main
140 # test-running process from all the signals. It then
141 # communicates with that child process over a pipe and
142 # re-raises information about any exceptions the child
Andrew Svetlov737fb892012-12-18 21:14:22 +0200143 # raises. The real work happens in self.run_test().
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000144 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000145 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
146 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000147 child = os.fork()
148 if child == 0:
149 # In the child process; run the test and report results
150 # through the pipe.
151 try:
152 done_r.close()
153 # Have to close done_w again here because
154 # exit_subprocess() will skip the enclosing with block.
155 with closing(done_w):
156 try:
157 self.run_test()
158 except:
159 pickle.dump(traceback.format_exc(), done_w)
160 else:
161 pickle.dump(None, done_w)
162 except:
163 print('Uh oh, raised from pickle.')
164 traceback.print_exc()
165 finally:
166 exit_subprocess()
167
168 done_w.close()
169 # Block for up to MAX_DURATION seconds for the test to finish.
170 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
171 if done_r in r:
172 tb = pickle.load(done_r)
173 if tb:
174 self.fail(tb)
175 else:
176 os.kill(child, signal.SIGKILL)
177 self.fail('Test deadlocked after %d seconds.' %
178 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000179
180
Brian Curtin3f004b12010-08-06 19:34:52 +0000181@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200182class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000183 def trivial_signal_handler(self, *args):
184 pass
185
Thomas Woutersed03b412007-08-28 21:37:11 +0000186 def test_out_of_range_signal_number_raises_error(self):
187 self.assertRaises(ValueError, signal.getsignal, 4242)
188
Thomas Woutersed03b412007-08-28 21:37:11 +0000189 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000190 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000191
192 def test_setting_signal_handler_to_none_raises_error(self):
193 self.assertRaises(TypeError, signal.signal,
194 signal.SIGUSR1, None)
195
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000196 def test_getsignal(self):
197 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000198 self.assertEqual(signal.getsignal(signal.SIGHUP),
199 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000200 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000201 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000202
203
Brian Curtin3f004b12010-08-06 19:34:52 +0000204@unittest.skipUnless(sys.platform == "win32", "Windows specific")
205class WindowsSignalTests(unittest.TestCase):
206 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000207 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000208 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +0000209 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
210 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
211 signal.SIGTERM):
212 # Set and then reset a handler for signals that work on windows
213 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin3f004b12010-08-06 19:34:52 +0000214
215 with self.assertRaises(ValueError):
216 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000217
218 with self.assertRaises(ValueError):
219 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000220
221
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500222class WakeupFDTests(unittest.TestCase):
223
224 def test_invalid_fd(self):
225 fd = support.make_bad_fd()
226 self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
227
228
Brian Curtin3f004b12010-08-06 19:34:52 +0000229@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000230class WakeupSignalTests(unittest.TestCase):
Charles-François Natali027f9a32011-10-02 18:36:05 +0200231 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200232 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200233 code = """if 1:
234 import fcntl
235 import os
236 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200237 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000238
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200239 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200240
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200241 def handler(signum, frame):
242 pass
243
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200244 def check_signum(signals):
245 data = os.read(read, len(signals)+1)
246 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200247 if not {!r}:
248 raised = set(raised)
249 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200250 if raised != signals:
251 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200252
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200253 {}
254
255 signal.signal(signal.SIGALRM, handler)
256 read, write = os.pipe()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200257 for fd in (read, write):
258 flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
259 flags = flags | os.O_NONBLOCK
260 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200261 signal.set_wakeup_fd(write)
262
263 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200264 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200265
266 os.close(read)
267 os.close(write)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200268 """.format(signals, ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200269
270 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200271
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000272 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200273 self.check_wakeup("""def test():
274 import select
275 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000276
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200277 TIMEOUT_FULL = 10
278 TIMEOUT_HALF = 5
279
280 signal.alarm(1)
281 before_time = time.time()
282 # We attempt to get a signal during the sleep,
283 # before select is called
284 time.sleep(TIMEOUT_FULL)
285 mid_time = time.time()
286 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200287 if dt >= TIMEOUT_HALF:
288 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200289 select.select([read], [], [], TIMEOUT_FULL)
290 after_time = time.time()
291 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200292 if dt >= TIMEOUT_HALF:
293 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200294 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000295
296 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200297 self.check_wakeup("""def test():
298 import select
299 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000300
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200301 TIMEOUT_FULL = 10
302 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000303
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200304 signal.alarm(1)
305 before_time = time.time()
306 # We attempt to get a signal during the select call
307 try:
308 select.select([read], [], [], TIMEOUT_FULL)
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200309 except OSError:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200310 pass
311 else:
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200312 raise Exception("OSError not raised")
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200313 after_time = time.time()
314 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200315 if dt >= TIMEOUT_HALF:
316 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200317 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200318
319 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200320 self.check_wakeup("""def test():
321 signal.signal(signal.SIGUSR1, handler)
322 os.kill(os.getpid(), signal.SIGUSR1)
323 os.kill(os.getpid(), signal.SIGALRM)
324 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000325
Victor Stinnerc13ef662011-05-25 02:35:58 +0200326 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
327 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200328 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200329 self.check_wakeup("""def test():
330 signum1 = signal.SIGUSR1
331 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200332
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200333 signal.signal(signum1, handler)
334 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200335
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200336 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
337 os.kill(os.getpid(), signum1)
338 os.kill(os.getpid(), signum2)
339 # Unblocking the 2 signals calls the C signal handler twice
340 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200341 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200342
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000343
Brian Curtin3f004b12010-08-06 19:34:52 +0000344@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000345class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000346
Victor Stinnerd6284962011-06-20 23:28:09 +0200347 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000348 """Perform a read during which a signal will arrive. Return True if the
349 read is interrupted by the signal and raises an exception. Return False
350 if it returns normally.
351 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200352 # use a subprocess to have only one thread, to have a timeout on the
353 # blocking read and to not touch signal handling in this process
354 code = """if 1:
355 import errno
356 import os
357 import signal
358 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000359
Victor Stinnerd6284962011-06-20 23:28:09 +0200360 interrupt = %r
361 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000362
Victor Stinnerd6284962011-06-20 23:28:09 +0200363 def handler(signum, frame):
364 pass
365
366 signal.signal(signal.SIGALRM, handler)
367 if interrupt is not None:
368 signal.siginterrupt(signal.SIGALRM, interrupt)
369
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200370 print("ready")
371 sys.stdout.flush()
372
Victor Stinnerd6284962011-06-20 23:28:09 +0200373 # run the test twice
374 for loop in range(2):
375 # send a SIGALRM in a second (during the read)
376 signal.alarm(1)
377 try:
378 # blocking call: read from a pipe without data
379 os.read(r, 1)
380 except OSError as err:
381 if err.errno != errno.EINTR:
382 raise
383 else:
384 sys.exit(2)
385 sys.exit(3)
386 """ % (interrupt,)
387 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000388 try:
Victor Stinner45273652011-06-22 22:15:51 +0200389 # wait until the child process is loaded and has started
390 first_line = process.stdout.readline()
391
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200392 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200393 except subprocess.TimeoutExpired:
394 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000395 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200396 else:
Victor Stinner45273652011-06-22 22:15:51 +0200397 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200398 exitcode = process.wait()
399 if exitcode not in (2, 3):
400 raise Exception("Child error (exit code %s): %s"
401 % (exitcode, stdout))
402 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000403
404 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200405 # If a signal handler is installed and siginterrupt is not called
406 # at all, when that signal arrives, it interrupts a syscall that's in
407 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200408 interrupted = self.readpipe_interrupted(None)
409 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000410
411 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200412 # If a signal handler is installed and siginterrupt is called with
413 # a true value for the second argument, when that signal arrives, it
414 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200415 interrupted = self.readpipe_interrupted(True)
416 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000417
418 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200419 # If a signal handler is installed and siginterrupt is called with
420 # a false value for the second argument, when that signal arrives, it
421 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200422 interrupted = self.readpipe_interrupted(False)
423 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000424
425
Brian Curtin3f004b12010-08-06 19:34:52 +0000426@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000427class ItimerTest(unittest.TestCase):
428 def setUp(self):
429 self.hndl_called = False
430 self.hndl_count = 0
431 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000432 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000433
434 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000435 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000436 if self.itimer is not None: # test_itimer_exc doesn't change this attr
437 # just ensure that itimer is stopped
438 signal.setitimer(self.itimer, 0)
439
440 def sig_alrm(self, *args):
441 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000442
443 def sig_vtalrm(self, *args):
444 self.hndl_called = True
445
446 if self.hndl_count > 3:
447 # it shouldn't be here, because it should have been disabled.
448 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
449 "timer.")
450 elif self.hndl_count == 3:
451 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
452 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000453
454 self.hndl_count += 1
455
Martin v. Löwis823725e2008-03-24 13:39:54 +0000456 def sig_prof(self, *args):
457 self.hndl_called = True
458 signal.setitimer(signal.ITIMER_PROF, 0)
459
Martin v. Löwis823725e2008-03-24 13:39:54 +0000460 def test_itimer_exc(self):
461 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
462 # defines it ?
463 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000464 # Negative times are treated as zero on some platforms.
465 if 0:
466 self.assertRaises(signal.ItimerError,
467 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000468
469 def test_itimer_real(self):
470 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000471 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000472 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000473 self.assertEqual(self.hndl_called, True)
474
R. David Murray44546f82010-04-21 01:59:28 +0000475 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000476 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
477 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000478 def test_itimer_virtual(self):
479 self.itimer = signal.ITIMER_VIRTUAL
480 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
481 signal.setitimer(self.itimer, 0.3, 0.2)
482
Mark Dickinson78373472009-10-31 10:39:21 +0000483 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000484 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000485 # use up some virtual time by doing real work
486 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000487 if signal.getitimer(self.itimer) == (0.0, 0.0):
488 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000489 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000490 self.skipTest("timeout: likely cause: machine too slow or load too "
491 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000492
493 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000494 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000495 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000496 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000497
R. David Murray44546f82010-04-21 01:59:28 +0000498 # Issue 3864, unknown if this affects earlier versions of freebsd also
499 @unittest.skipIf(sys.platform=='freebsd6',
500 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000501 def test_itimer_prof(self):
502 self.itimer = signal.ITIMER_PROF
503 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000504 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000505
Mark Dickinson78373472009-10-31 10:39:21 +0000506 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000507 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000508 # do some work
509 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000510 if signal.getitimer(self.itimer) == (0.0, 0.0):
511 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000512 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000513 self.skipTest("timeout: likely cause: machine too slow or load too "
514 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000515
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000516 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000517 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000518 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000519 self.assertEqual(self.hndl_called, True)
520
Victor Stinnera9293352011-04-30 15:21:58 +0200521
Victor Stinner35b300c2011-05-04 13:20:35 +0200522class PendingSignalsTests(unittest.TestCase):
523 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200524 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
525 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200526 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200527 @unittest.skipUnless(hasattr(signal, 'sigpending'),
528 'need signal.sigpending()')
529 def test_sigpending_empty(self):
530 self.assertEqual(signal.sigpending(), set())
531
532 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
533 'need signal.pthread_sigmask()')
534 @unittest.skipUnless(hasattr(signal, 'sigpending'),
535 'need signal.sigpending()')
536 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200537 code = """if 1:
538 import os
539 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200540
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200541 def handler(signum, frame):
542 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200543
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200544 signum = signal.SIGUSR1
545 signal.signal(signum, handler)
546
547 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
548 os.kill(os.getpid(), signum)
549 pending = signal.sigpending()
Victor Stinner0a01f132011-07-04 18:06:35 +0200550 if pending != {signum}:
551 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200552 try:
553 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
554 except ZeroDivisionError:
555 pass
556 else:
557 raise Exception("ZeroDivisionError not raised")
558 """
559 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200560
561 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
562 'need signal.pthread_kill()')
563 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200564 code = """if 1:
565 import signal
566 import threading
567 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200568
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200569 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200570
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200571 def handler(signum, frame):
572 1/0
573
574 signal.signal(signum, handler)
575
576 if sys.platform == 'freebsd6':
577 # Issue #12392 and #12469: send a signal to the main thread
578 # doesn't work before the creation of the first thread on
579 # FreeBSD 6
580 def noop():
581 pass
582 thread = threading.Thread(target=noop)
583 thread.start()
584 thread.join()
585
586 tid = threading.get_ident()
587 try:
588 signal.pthread_kill(tid, signum)
589 except ZeroDivisionError:
590 pass
591 else:
592 raise Exception("ZeroDivisionError not raised")
593 """
594 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200595
Victor Stinner7f294d12011-06-10 14:02:10 +0200596 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
597 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200598 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200599 """
600 test: body of the "def test(signum):" function.
601 blocked: number of the blocked signal
602 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200603 code = '''if 1:
604 import signal
605 import sys
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200606
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200607 def handler(signum, frame):
608 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200609
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200610 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200611
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200612 blocked = %s
613 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200614
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200615 # child: block and wait the signal
616 try:
617 signal.signal(signum, handler)
618 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200619
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200620 # Do the tests
621 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200622
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200623 # The handler must not be called on unblock
624 try:
625 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
626 except ZeroDivisionError:
627 print("the signal handler has been called",
628 file=sys.stderr)
629 sys.exit(1)
630 except BaseException as err:
631 print("error: {}".format(err), file=sys.stderr)
632 sys.stderr.flush()
633 sys.exit(1)
634 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200635
Ross Lagerwallbc808222011-06-25 12:13:40 +0200636 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200637 # process might have several threads running, use a subprocess to have
638 # a single thread.
639 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200640
Victor Stinnerb3e72192011-05-08 01:46:11 +0200641 @unittest.skipUnless(hasattr(signal, 'sigwait'),
642 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200643 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200644 self.wait_helper(signal.SIGALRM, '''
645 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200646 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200647 received = signal.sigwait([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200648 if received != signum:
649 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200650 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200651
652 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
653 'need signal.sigwaitinfo()')
654 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200655 self.wait_helper(signal.SIGALRM, '''
656 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200657 signal.alarm(1)
658 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200659 if info.si_signo != signum:
660 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200661 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200662
663 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
664 'need signal.sigtimedwait()')
665 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200666 self.wait_helper(signal.SIGALRM, '''
667 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200668 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100669 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200670 if info.si_signo != signum:
671 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200672 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200673
Ross Lagerwallbc808222011-06-25 12:13:40 +0200674 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
675 'need signal.sigtimedwait()')
676 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)
Victor Stinner643cd682012-03-02 22:54:03 +0100682 info = signal.sigtimedwait([signum], 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 Stinner643cd682012-03-02 22:54:03 +0100692 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
Victor Stinner643cd682012-03-02 22:54:03 +0100701 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200702
Ross Lagerwallbc808222011-06-25 12:13:40 +0200703 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
704 'need signal.sigwaitinfo()')
705 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200706 self.wait_helper(signal.SIGUSR1, '''
707 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200708 import errno
709
710 hndl_called = True
711 def alarm_handler(signum, frame):
712 hndl_called = False
713
714 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200715 signal.alarm(1)
716 try:
717 signal.sigwaitinfo([signal.SIGUSR1])
718 except OSError as e:
719 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200720 if not hndl_called:
721 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200722 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200723 raise Exception("Expected EINTR to be raised by sigwaitinfo")
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")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200726 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200727
728 @unittest.skipUnless(hasattr(signal, 'sigwait'),
729 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200730 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
731 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200732 @unittest.skipIf(threading is None, "test needs threading module")
733 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200734 # Check that calling sigwait() from a thread doesn't suspend the whole
735 # process. A new interpreter is spawned to avoid problems when mixing
736 # threads and fork(): only async-safe functions are allowed between
737 # fork() and exec().
738 assert_python_ok("-c", """if True:
739 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200740
Victor Stinner415007e2011-06-13 16:19:06 +0200741 # the default handler terminates the process
742 signum = signal.SIGUSR1
743
744 def kill_later():
745 # wait until the main thread is waiting in sigwait()
746 time.sleep(1)
747 os.kill(os.getpid(), signum)
748
749 # the signal must be blocked by all the threads
750 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
751 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200752 killer.start()
753 received = signal.sigwait([signum])
754 if received != signum:
755 print("sigwait() received %s, not %s" % (received, signum),
756 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200757 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200758 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200759 # unblock the signal, which should have been cleared by sigwait()
760 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
761 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200762
Victor Stinnerb3e72192011-05-08 01:46:11 +0200763 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
764 'need signal.pthread_sigmask()')
765 def test_pthread_sigmask_arguments(self):
766 self.assertRaises(TypeError, signal.pthread_sigmask)
767 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
768 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
769 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
770
771 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
772 'need signal.pthread_sigmask()')
773 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200774 code = """if 1:
775 import signal
776 import os; import threading
777
778 def handler(signum, frame):
779 1/0
780
781 def kill(signum):
782 os.kill(os.getpid(), signum)
783
784 def read_sigmask():
785 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
786
Victor Stinnerb3e72192011-05-08 01:46:11 +0200787 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200788
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200789 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200790 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200791
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200792 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200793 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200794 try:
795 kill(signum)
796 except ZeroDivisionError:
797 pass
798 else:
799 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200800
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200801 # Block and then raise SIGUSR1. The signal is blocked: the signal
802 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200803 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200804 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200805
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200806 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200807 blocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200808 if signum not in blocked:
809 raise Exception("%s not in %s" % (signum, blocked))
810 if old_mask ^ blocked != {signum}:
811 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200812
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200813 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200814 try:
815 # unblock the pending signal calls immediatly the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200816 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200817 except ZeroDivisionError:
818 pass
819 else:
820 raise Exception("ZeroDivisionError not raised")
821 try:
822 kill(signum)
823 except ZeroDivisionError:
824 pass
825 else:
826 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200827
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200828 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200829 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200830 if signum in unblocked:
831 raise Exception("%s in %s" % (signum, unblocked))
832 if blocked ^ unblocked != {signum}:
833 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
834 if old_mask != unblocked:
835 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200836 """
837 assert_python_ok('-c', code)
838
839 @unittest.skipIf(sys.platform == 'freebsd6',
840 "issue #12392: send a signal to the main thread doesn't work "
841 "before the creation of the first thread on FreeBSD 6")
842 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
843 'need signal.pthread_kill()')
844 def test_pthread_kill_main_thread(self):
845 # Test that a signal can be sent to the main thread with pthread_kill()
846 # before any other thread has been created (see issue #12392).
847 code = """if True:
848 import threading
849 import signal
850 import sys
851
852 def handler(signum, frame):
853 sys.exit(3)
854
855 signal.signal(signal.SIGUSR1, handler)
856 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
857 sys.exit(2)
858 """
859
860 with spawn_python('-c', code) as process:
861 stdout, stderr = process.communicate()
862 exitcode = process.wait()
863 if exitcode != 3:
864 raise Exception("Child error (exit code %s): %s" %
865 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200866
867
Thomas Woutersed03b412007-08-28 21:37:11 +0000868def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100869 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200870 support.run_unittest(PosixTests, InterProcessSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500871 WakeupFDTests, WakeupSignalTests,
872 SiginterruptTest, ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200873 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100874 finally:
875 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000876
877
878if __name__ == "__main__":
879 test_main()