blob: ab42ed70cc91baf7201cd993f40e0d0d8951ca5e [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
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02004import enum
Christian Heimescc47b052008-03-25 14:56:36 +00005import gc
Christian Heimes4fbc72b2008-03-22 00:47:35 +00006import pickle
7import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00008import signal
Victor Stinner11517102014-07-29 23:31:34 +02009import socket
Victor Stinnerd49b1f12011-05-08 02:03:15 +020010import struct
Christian Heimes4fbc72b2008-03-22 00:47:35 +000011import subprocess
12import traceback
Christian Heimesc06950e2008-02-28 21:17:00 +000013import sys, os, time, errno
Berker Peksagce643912015-05-06 06:33:17 +030014from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020015try:
16 import threading
17except ImportError:
18 threading = None
Victor Stinner56e8c292014-07-21 12:30:22 +020019try:
20 import _testcapi
21except ImportError:
22 _testcapi = None
Christian Heimesc06950e2008-02-28 21:17:00 +000023
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000024
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020025class GenericTests(unittest.TestCase):
26
Stefan Krah63c4b242014-04-15 22:40:06 +020027 @unittest.skipIf(threading is None, "test needs threading module")
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020028 def test_enums(self):
29 for name in dir(signal):
30 sig = getattr(signal, name)
31 if name in {'SIG_DFL', 'SIG_IGN'}:
32 self.assertIsInstance(sig, signal.Handlers)
33 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
34 self.assertIsInstance(sig, signal.Sigmasks)
35 elif name.startswith('SIG') and not name.startswith('SIG_'):
36 self.assertIsInstance(sig, signal.Signals)
37 elif name.startswith('CTRL_'):
38 self.assertIsInstance(sig, signal.Signals)
39 self.assertEqual(sys.platform, "win32")
40
41
Brian Curtin3f004b12010-08-06 19:34:52 +000042@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +020043class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +000044 def trivial_signal_handler(self, *args):
45 pass
46
Thomas Woutersed03b412007-08-28 21:37:11 +000047 def test_out_of_range_signal_number_raises_error(self):
48 self.assertRaises(ValueError, signal.getsignal, 4242)
49
Thomas Woutersed03b412007-08-28 21:37:11 +000050 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +000051 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +000052
53 def test_setting_signal_handler_to_none_raises_error(self):
54 self.assertRaises(TypeError, signal.signal,
55 signal.SIGUSR1, None)
56
Christian Heimes4fbc72b2008-03-22 00:47:35 +000057 def test_getsignal(self):
58 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020059 self.assertIsInstance(hup, signal.Handlers)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000060 self.assertEqual(signal.getsignal(signal.SIGHUP),
61 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000062 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000063 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000064
Victor Stinner32eb8402016-03-15 11:12:35 +010065 # Issue 3864, unknown if this affects earlier versions of freebsd also
66 @unittest.skipIf(sys.platform=='freebsd6',
67 'inter process signals not reliable (do not mix well with threading) '
68 'on freebsd6')
69 def test_interprocess_signal(self):
70 dirname = os.path.dirname(__file__)
71 script = os.path.join(dirname, 'signalinterproctester.py')
72 assert_python_ok(script)
73
Christian Heimes4fbc72b2008-03-22 00:47:35 +000074
Brian Curtin3f004b12010-08-06 19:34:52 +000075@unittest.skipUnless(sys.platform == "win32", "Windows specific")
76class WindowsSignalTests(unittest.TestCase):
77 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +000078 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +000079 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +100080 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +000081 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
82 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
83 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +100084 # Set and then reset a handler for signals that work on windows.
85 # Issue #18396, only for signals without a C-level handler.
86 if signal.getsignal(sig) is not None:
87 signal.signal(sig, signal.signal(sig, handler))
88 checked.add(sig)
89 # Issue #18396: Ensure the above loop at least tested *something*
90 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +000091
92 with self.assertRaises(ValueError):
93 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +000094
95 with self.assertRaises(ValueError):
96 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +000097
98
Benjamin Petersonc68a4a02013-01-18 00:10:24 -050099class WakeupFDTests(unittest.TestCase):
100
101 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200102 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +0200103 self.assertRaises((ValueError, OSError),
104 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500105
Victor Stinner11517102014-07-29 23:31:34 +0200106 def test_invalid_socket(self):
107 sock = socket.socket()
108 fd = sock.fileno()
109 sock.close()
110 self.assertRaises((ValueError, OSError),
111 signal.set_wakeup_fd, fd)
112
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200113 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200114 r1, w1 = os.pipe()
115 self.addCleanup(os.close, r1)
116 self.addCleanup(os.close, w1)
117 r2, w2 = os.pipe()
118 self.addCleanup(os.close, r2)
119 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200120
Victor Stinner7cea44d2014-08-27 14:02:36 +0200121 if hasattr(os, 'set_blocking'):
122 os.set_blocking(w1, False)
123 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200124
Victor Stinner1d8948e2014-07-24 22:51:05 +0200125 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200126 self.assertEqual(signal.set_wakeup_fd(w2), w1)
127 self.assertEqual(signal.set_wakeup_fd(-1), w2)
128 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200129
Victor Stinner11517102014-07-29 23:31:34 +0200130 def test_set_wakeup_fd_socket_result(self):
131 sock1 = socket.socket()
132 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200133 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200134 fd1 = sock1.fileno()
135
136 sock2 = socket.socket()
137 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200138 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200139 fd2 = sock2.fileno()
140
141 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200142 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
143 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
144 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200145
Victor Stinner38227602014-08-27 12:59:44 +0200146 # On Windows, files are always blocking and Windows does not provide a
147 # function to test if a socket is in non-blocking mode.
148 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
149 def test_set_wakeup_fd_blocking(self):
150 rfd, wfd = os.pipe()
151 self.addCleanup(os.close, rfd)
152 self.addCleanup(os.close, wfd)
153
154 # fd must be non-blocking
155 os.set_blocking(wfd, True)
156 with self.assertRaises(ValueError) as cm:
157 signal.set_wakeup_fd(wfd)
158 self.assertEqual(str(cm.exception),
159 "the fd %s must be in non-blocking mode" % wfd)
160
161 # non-blocking is ok
162 os.set_blocking(wfd, False)
163 signal.set_wakeup_fd(wfd)
164 signal.set_wakeup_fd(-1)
165
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500166
Brian Curtin3f004b12010-08-06 19:34:52 +0000167@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000168class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200169 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200170 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200171 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200172 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200173 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200174 import os
175 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200176 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000177
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200178 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200179
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200180 def handler(signum, frame):
181 pass
182
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200183 def check_signum(signals):
184 data = os.read(read, len(signals)+1)
185 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200186 if not {!r}:
187 raised = set(raised)
188 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200189 if raised != signals:
190 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200191
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200192 {}
193
194 signal.signal(signal.SIGALRM, handler)
195 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200196 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200197 signal.set_wakeup_fd(write)
198
199 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200200 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200201
202 os.close(read)
203 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200204 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200205
206 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200207
Victor Stinner56e8c292014-07-21 12:30:22 +0200208 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200209 def test_wakeup_write_error(self):
210 # Issue #16105: write() errors in the C signal handler should not
211 # pass silently.
212 # Use a subprocess to have only one thread.
213 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200214 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200215 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200216 import os
217 import signal
218 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200219 from test.support import captured_stderr
220
221 def handler(signum, frame):
222 1/0
223
224 signal.signal(signal.SIGALRM, handler)
225 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200226 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200227
228 # Set wakeup_fd a read-only file descriptor to trigger the error
229 signal.set_wakeup_fd(r)
230 try:
231 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200232 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200233 except ZeroDivisionError:
234 # An ignored exception should have been printed out on stderr
235 err = err.getvalue()
236 if ('Exception ignored when trying to write to the signal wakeup fd'
237 not in err):
238 raise AssertionError(err)
239 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
240 raise AssertionError(err)
241 else:
242 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200243
244 os.close(r)
245 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200246 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200247 r, w = os.pipe()
248 try:
249 os.write(r, b'x')
250 except OSError:
251 pass
252 else:
253 self.skipTest("OS doesn't report write() error on the read end of a pipe")
254 finally:
255 os.close(r)
256 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200257
258 assert_python_ok('-c', code)
259
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000260 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200261 self.check_wakeup("""def test():
262 import select
263 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000264
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200265 TIMEOUT_FULL = 10
266 TIMEOUT_HALF = 5
267
Victor Stinner749a6a82015-03-30 22:09:14 +0200268 class InterruptSelect(Exception):
269 pass
270
271 def handler(signum, frame):
272 raise InterruptSelect
273 signal.signal(signal.SIGALRM, handler)
274
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200275 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100276
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200277 # We attempt to get a signal during the sleep,
278 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100279 try:
280 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200281 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100282 pass
283 else:
284 raise Exception("select() was not interrupted")
285
286 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200287 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100288 after_time = time.monotonic()
289 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200290 if dt >= TIMEOUT_HALF:
291 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200292 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000293
294 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200295 self.check_wakeup("""def test():
296 import select
297 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000298
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200299 TIMEOUT_FULL = 10
300 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000301
Victor Stinner749a6a82015-03-30 22:09:14 +0200302 class InterruptSelect(Exception):
303 pass
304
305 def handler(signum, frame):
306 raise InterruptSelect
307 signal.signal(signal.SIGALRM, handler)
308
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200309 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100310 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200311 # We attempt to get a signal during the select call
312 try:
313 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200314 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200315 pass
316 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200317 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100318 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200319 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200320 if dt >= TIMEOUT_HALF:
321 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200322 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200323
324 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200325 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200326 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200327 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200328 _testcapi.raise_signal(signal.SIGUSR1)
329 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200330 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000331
Victor Stinnerc13ef662011-05-25 02:35:58 +0200332 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
333 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200334 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200335 self.check_wakeup("""def test():
336 signum1 = signal.SIGUSR1
337 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200338
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200339 signal.signal(signum1, handler)
340 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200341
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200342 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200343 _testcapi.raise_signal(signum1)
344 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200345 # Unblocking the 2 signals calls the C signal handler twice
346 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200347 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200348
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000349
Victor Stinner11517102014-07-29 23:31:34 +0200350@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
351class WakeupSocketSignalTests(unittest.TestCase):
352
353 @unittest.skipIf(_testcapi is None, 'need _testcapi')
354 def test_socket(self):
355 # use a subprocess to have only one thread
356 code = """if 1:
357 import signal
358 import socket
359 import struct
360 import _testcapi
361
362 signum = signal.SIGINT
363 signals = (signum,)
364
365 def handler(signum, frame):
366 pass
367
368 signal.signal(signum, handler)
369
370 read, write = socket.socketpair()
371 read.setblocking(False)
372 write.setblocking(False)
373 signal.set_wakeup_fd(write.fileno())
374
375 _testcapi.raise_signal(signum)
376
377 data = read.recv(1)
378 if not data:
379 raise Exception("no signum written")
380 raised = struct.unpack('B', data)
381 if raised != signals:
382 raise Exception("%r != %r" % (raised, signals))
383
384 read.close()
385 write.close()
386 """
387
388 assert_python_ok('-c', code)
389
390 @unittest.skipIf(_testcapi is None, 'need _testcapi')
391 def test_send_error(self):
392 # Use a subprocess to have only one thread.
393 if os.name == 'nt':
394 action = 'send'
395 else:
396 action = 'write'
397 code = """if 1:
398 import errno
399 import signal
400 import socket
401 import sys
402 import time
403 import _testcapi
404 from test.support import captured_stderr
405
406 signum = signal.SIGINT
407
408 def handler(signum, frame):
409 pass
410
411 signal.signal(signum, handler)
412
413 read, write = socket.socketpair()
414 read.setblocking(False)
415 write.setblocking(False)
416
417 signal.set_wakeup_fd(write.fileno())
418
419 # Close sockets: send() will fail
420 read.close()
421 write.close()
422
423 with captured_stderr() as err:
424 _testcapi.raise_signal(signum)
425
426 err = err.getvalue()
427 if ('Exception ignored when trying to {action} to the signal wakeup fd'
428 not in err):
429 raise AssertionError(err)
430 """.format(action=action)
431 assert_python_ok('-c', code)
432
433
Brian Curtin3f004b12010-08-06 19:34:52 +0000434@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000435class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000436
Victor Stinnerd6284962011-06-20 23:28:09 +0200437 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000438 """Perform a read during which a signal will arrive. Return True if the
439 read is interrupted by the signal and raises an exception. Return False
440 if it returns normally.
441 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200442 # use a subprocess to have only one thread, to have a timeout on the
443 # blocking read and to not touch signal handling in this process
444 code = """if 1:
445 import errno
446 import os
447 import signal
448 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000449
Victor Stinnerd6284962011-06-20 23:28:09 +0200450 interrupt = %r
451 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000452
Victor Stinnerd6284962011-06-20 23:28:09 +0200453 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000454 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200455
456 signal.signal(signal.SIGALRM, handler)
457 if interrupt is not None:
458 signal.siginterrupt(signal.SIGALRM, interrupt)
459
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200460 print("ready")
461 sys.stdout.flush()
462
Victor Stinnerd6284962011-06-20 23:28:09 +0200463 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200464 try:
465 for loop in range(2):
466 # send a SIGALRM in a second (during the read)
467 signal.alarm(1)
468 try:
469 # blocking call: read from a pipe without data
470 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000471 except ZeroDivisionError:
472 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200473 else:
474 sys.exit(2)
475 sys.exit(3)
476 finally:
477 os.close(r)
478 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200479 """ % (interrupt,)
480 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000481 try:
Victor Stinner45273652011-06-22 22:15:51 +0200482 # wait until the child process is loaded and has started
483 first_line = process.stdout.readline()
484
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200485 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200486 except subprocess.TimeoutExpired:
487 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000488 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200489 else:
Victor Stinner45273652011-06-22 22:15:51 +0200490 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200491 exitcode = process.wait()
492 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200493 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200494 % (exitcode, stdout))
495 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000496
497 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200498 # If a signal handler is installed and siginterrupt is not called
499 # at all, when that signal arrives, it interrupts a syscall that's in
500 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200501 interrupted = self.readpipe_interrupted(None)
502 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000503
504 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200505 # If a signal handler is installed and siginterrupt is called with
506 # a true value for the second argument, when that signal arrives, it
507 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200508 interrupted = self.readpipe_interrupted(True)
509 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000510
511 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200512 # If a signal handler is installed and siginterrupt is called with
513 # a false value for the second argument, when that signal arrives, it
514 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200515 interrupted = self.readpipe_interrupted(False)
516 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000517
518
Brian Curtin3f004b12010-08-06 19:34:52 +0000519@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000520class ItimerTest(unittest.TestCase):
521 def setUp(self):
522 self.hndl_called = False
523 self.hndl_count = 0
524 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000525 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000526
527 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000528 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000529 if self.itimer is not None: # test_itimer_exc doesn't change this attr
530 # just ensure that itimer is stopped
531 signal.setitimer(self.itimer, 0)
532
533 def sig_alrm(self, *args):
534 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000535
536 def sig_vtalrm(self, *args):
537 self.hndl_called = True
538
539 if self.hndl_count > 3:
540 # it shouldn't be here, because it should have been disabled.
541 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
542 "timer.")
543 elif self.hndl_count == 3:
544 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
545 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000546
547 self.hndl_count += 1
548
Martin v. Löwis823725e2008-03-24 13:39:54 +0000549 def sig_prof(self, *args):
550 self.hndl_called = True
551 signal.setitimer(signal.ITIMER_PROF, 0)
552
Martin v. Löwis823725e2008-03-24 13:39:54 +0000553 def test_itimer_exc(self):
554 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
555 # defines it ?
556 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000557 # Negative times are treated as zero on some platforms.
558 if 0:
559 self.assertRaises(signal.ItimerError,
560 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000561
562 def test_itimer_real(self):
563 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000564 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000565 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000566 self.assertEqual(self.hndl_called, True)
567
R. David Murray44546f82010-04-21 01:59:28 +0000568 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000569 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
570 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000571 def test_itimer_virtual(self):
572 self.itimer = signal.ITIMER_VIRTUAL
573 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
574 signal.setitimer(self.itimer, 0.3, 0.2)
575
Victor Stinner79d68f92015-03-19 21:54:09 +0100576 start_time = time.monotonic()
577 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000578 # use up some virtual time by doing real work
579 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000580 if signal.getitimer(self.itimer) == (0.0, 0.0):
581 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000582 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000583 self.skipTest("timeout: likely cause: machine too slow or load too "
584 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000585
586 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000587 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000588 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000589 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000590
R. David Murray44546f82010-04-21 01:59:28 +0000591 # Issue 3864, unknown if this affects earlier versions of freebsd also
592 @unittest.skipIf(sys.platform=='freebsd6',
593 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000594 def test_itimer_prof(self):
595 self.itimer = signal.ITIMER_PROF
596 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000597 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000598
Victor Stinner79d68f92015-03-19 21:54:09 +0100599 start_time = time.monotonic()
600 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000601 # do some work
602 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000603 if signal.getitimer(self.itimer) == (0.0, 0.0):
604 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000605 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000606 self.skipTest("timeout: likely cause: machine too slow or load too "
607 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000608
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000609 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000610 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000611 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000612 self.assertEqual(self.hndl_called, True)
613
Victor Stinnera9293352011-04-30 15:21:58 +0200614
Victor Stinner35b300c2011-05-04 13:20:35 +0200615class PendingSignalsTests(unittest.TestCase):
616 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200617 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
618 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200619 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200620 @unittest.skipUnless(hasattr(signal, 'sigpending'),
621 'need signal.sigpending()')
622 def test_sigpending_empty(self):
623 self.assertEqual(signal.sigpending(), set())
624
625 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
626 'need signal.pthread_sigmask()')
627 @unittest.skipUnless(hasattr(signal, 'sigpending'),
628 'need signal.sigpending()')
629 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200630 code = """if 1:
631 import os
632 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200633
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200634 def handler(signum, frame):
635 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200636
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200637 signum = signal.SIGUSR1
638 signal.signal(signum, handler)
639
640 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
641 os.kill(os.getpid(), signum)
642 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200643 for sig in pending:
644 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200645 if pending != {signum}:
646 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200647 try:
648 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
649 except ZeroDivisionError:
650 pass
651 else:
652 raise Exception("ZeroDivisionError not raised")
653 """
654 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200655
656 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
657 'need signal.pthread_kill()')
658 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200659 code = """if 1:
660 import signal
661 import threading
662 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200663
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200664 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200665
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200666 def handler(signum, frame):
667 1/0
668
669 signal.signal(signum, handler)
670
671 if sys.platform == 'freebsd6':
672 # Issue #12392 and #12469: send a signal to the main thread
673 # doesn't work before the creation of the first thread on
674 # FreeBSD 6
675 def noop():
676 pass
677 thread = threading.Thread(target=noop)
678 thread.start()
679 thread.join()
680
681 tid = threading.get_ident()
682 try:
683 signal.pthread_kill(tid, signum)
684 except ZeroDivisionError:
685 pass
686 else:
687 raise Exception("ZeroDivisionError not raised")
688 """
689 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200690
Victor Stinner7f294d12011-06-10 14:02:10 +0200691 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
692 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200693 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200694 """
695 test: body of the "def test(signum):" function.
696 blocked: number of the blocked signal
697 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200698 code = '''if 1:
699 import signal
700 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200701 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200702
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200703 def handler(signum, frame):
704 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200705
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200706 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200707
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200708 blocked = %s
709 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200710
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200711 # child: block and wait the signal
712 try:
713 signal.signal(signum, handler)
714 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200715
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200716 # Do the tests
717 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200718
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200719 # The handler must not be called on unblock
720 try:
721 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
722 except ZeroDivisionError:
723 print("the signal handler has been called",
724 file=sys.stderr)
725 sys.exit(1)
726 except BaseException as err:
727 print("error: {}".format(err), file=sys.stderr)
728 sys.stderr.flush()
729 sys.exit(1)
730 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200731
Ross Lagerwallbc808222011-06-25 12:13:40 +0200732 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200733 # process might have several threads running, use a subprocess to have
734 # a single thread.
735 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200736
Victor Stinnerb3e72192011-05-08 01:46:11 +0200737 @unittest.skipUnless(hasattr(signal, 'sigwait'),
738 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200739 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200740 self.wait_helper(signal.SIGALRM, '''
741 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200742 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200743 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200744 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200745 if received != signum:
746 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200747 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200748
749 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
750 'need signal.sigwaitinfo()')
751 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200752 self.wait_helper(signal.SIGALRM, '''
753 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200754 signal.alarm(1)
755 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200756 if info.si_signo != signum:
757 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200758 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200759
760 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
761 'need signal.sigtimedwait()')
762 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200763 self.wait_helper(signal.SIGALRM, '''
764 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200765 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100766 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200767 if info.si_signo != signum:
768 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200769 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200770
Ross Lagerwallbc808222011-06-25 12:13:40 +0200771 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
772 'need signal.sigtimedwait()')
773 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200774 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200775 self.wait_helper(signal.SIGALRM, '''
776 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200777 import os
778 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100779 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200780 if info.si_signo != signum:
781 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200782 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200783
784 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
785 'need signal.sigtimedwait()')
786 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200787 self.wait_helper(signal.SIGALRM, '''
788 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100789 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200790 if received is not None:
791 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200792 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200793
794 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
795 'need signal.sigtimedwait()')
796 def test_sigtimedwait_negative_timeout(self):
797 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100798 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200799
Ross Lagerwallbc808222011-06-25 12:13:40 +0200800 @unittest.skipUnless(hasattr(signal, 'sigwait'),
801 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200802 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
803 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200804 @unittest.skipIf(threading is None, "test needs threading module")
805 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200806 # Check that calling sigwait() from a thread doesn't suspend the whole
807 # process. A new interpreter is spawned to avoid problems when mixing
808 # threads and fork(): only async-safe functions are allowed between
809 # fork() and exec().
810 assert_python_ok("-c", """if True:
811 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200812
Victor Stinner415007e2011-06-13 16:19:06 +0200813 # the default handler terminates the process
814 signum = signal.SIGUSR1
815
816 def kill_later():
817 # wait until the main thread is waiting in sigwait()
818 time.sleep(1)
819 os.kill(os.getpid(), signum)
820
821 # the signal must be blocked by all the threads
822 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
823 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200824 killer.start()
825 received = signal.sigwait([signum])
826 if received != signum:
827 print("sigwait() received %s, not %s" % (received, signum),
828 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200829 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200830 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200831 # unblock the signal, which should have been cleared by sigwait()
832 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
833 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200834
Victor Stinnerb3e72192011-05-08 01:46:11 +0200835 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
836 'need signal.pthread_sigmask()')
837 def test_pthread_sigmask_arguments(self):
838 self.assertRaises(TypeError, signal.pthread_sigmask)
839 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
840 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
841 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
842
843 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
844 'need signal.pthread_sigmask()')
845 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200846 code = """if 1:
847 import signal
848 import os; import threading
849
850 def handler(signum, frame):
851 1/0
852
853 def kill(signum):
854 os.kill(os.getpid(), signum)
855
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200856 def check_mask(mask):
857 for sig in mask:
858 assert isinstance(sig, signal.Signals), repr(sig)
859
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200860 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200861 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
862 check_mask(sigmask)
863 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200864
Victor Stinnerb3e72192011-05-08 01:46:11 +0200865 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200866
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200867 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200868 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200869
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200870 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200871 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200872 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200873 try:
874 kill(signum)
875 except ZeroDivisionError:
876 pass
877 else:
878 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200879
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200880 # Block and then raise SIGUSR1. The signal is blocked: the signal
881 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200882 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
883 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200884 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200885
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200886 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200887 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200888 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +0200889 if signum not in blocked:
890 raise Exception("%s not in %s" % (signum, blocked))
891 if old_mask ^ blocked != {signum}:
892 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200893
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200894 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200895 try:
R David Murrayfc069992013-12-13 20:52:19 -0500896 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200897 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200898 except ZeroDivisionError:
899 pass
900 else:
901 raise Exception("ZeroDivisionError not raised")
902 try:
903 kill(signum)
904 except ZeroDivisionError:
905 pass
906 else:
907 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200908
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200909 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200910 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200911 if signum in unblocked:
912 raise Exception("%s in %s" % (signum, unblocked))
913 if blocked ^ unblocked != {signum}:
914 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
915 if old_mask != unblocked:
916 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200917 """
918 assert_python_ok('-c', code)
919
920 @unittest.skipIf(sys.platform == 'freebsd6',
921 "issue #12392: send a signal to the main thread doesn't work "
922 "before the creation of the first thread on FreeBSD 6")
923 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
924 'need signal.pthread_kill()')
925 def test_pthread_kill_main_thread(self):
926 # Test that a signal can be sent to the main thread with pthread_kill()
927 # before any other thread has been created (see issue #12392).
928 code = """if True:
929 import threading
930 import signal
931 import sys
932
933 def handler(signum, frame):
934 sys.exit(3)
935
936 signal.signal(signal.SIGUSR1, handler)
937 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
938 sys.exit(2)
939 """
940
941 with spawn_python('-c', code) as process:
942 stdout, stderr = process.communicate()
943 exitcode = process.wait()
944 if exitcode != 3:
945 raise Exception("Child error (exit code %s): %s" %
946 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200947
948
Zachary Ware38c707e2015-04-13 15:00:43 -0500949def tearDownModule():
950 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000951
952if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500953 unittest.main()