blob: 22715cf64e0033f56cd4dee963b2a1fb2fa134be [file] [log] [blame]
Victor Stinnerd6debb22017-03-27 16:05:26 +02001import os
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00002import signal
Victor Stinner11517102014-07-29 23:31:34 +02003import socket
Christian Heimes4fbc72b2008-03-22 00:47:35 +00004import subprocess
Victor Stinnerd6debb22017-03-27 16:05:26 +02005import sys
6import time
7import unittest
8from test import support
Berker Peksagce643912015-05-06 06:33:17 +03009from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020010try:
11 import threading
12except ImportError:
13 threading = None
Victor Stinner56e8c292014-07-21 12:30:22 +020014try:
15 import _testcapi
16except ImportError:
17 _testcapi = None
Christian Heimesc06950e2008-02-28 21:17:00 +000018
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000019
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020020class GenericTests(unittest.TestCase):
21
Stefan Krah63c4b242014-04-15 22:40:06 +020022 @unittest.skipIf(threading is None, "test needs threading module")
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020023 def test_enums(self):
24 for name in dir(signal):
25 sig = getattr(signal, name)
26 if name in {'SIG_DFL', 'SIG_IGN'}:
27 self.assertIsInstance(sig, signal.Handlers)
28 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
29 self.assertIsInstance(sig, signal.Sigmasks)
30 elif name.startswith('SIG') and not name.startswith('SIG_'):
31 self.assertIsInstance(sig, signal.Signals)
32 elif name.startswith('CTRL_'):
33 self.assertIsInstance(sig, signal.Signals)
34 self.assertEqual(sys.platform, "win32")
35
36
Brian Curtin3f004b12010-08-06 19:34:52 +000037@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +020038class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +000039 def trivial_signal_handler(self, *args):
40 pass
41
Thomas Woutersed03b412007-08-28 21:37:11 +000042 def test_out_of_range_signal_number_raises_error(self):
43 self.assertRaises(ValueError, signal.getsignal, 4242)
44
Thomas Woutersed03b412007-08-28 21:37:11 +000045 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +000046 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +000047
48 def test_setting_signal_handler_to_none_raises_error(self):
49 self.assertRaises(TypeError, signal.signal,
50 signal.SIGUSR1, None)
51
Christian Heimes4fbc72b2008-03-22 00:47:35 +000052 def test_getsignal(self):
53 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020054 self.assertIsInstance(hup, signal.Handlers)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000055 self.assertEqual(signal.getsignal(signal.SIGHUP),
56 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000057 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000058 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000059
Victor Stinner32eb8402016-03-15 11:12:35 +010060 # Issue 3864, unknown if this affects earlier versions of freebsd also
61 @unittest.skipIf(sys.platform=='freebsd6',
62 'inter process signals not reliable (do not mix well with threading) '
63 'on freebsd6')
64 def test_interprocess_signal(self):
65 dirname = os.path.dirname(__file__)
66 script = os.path.join(dirname, 'signalinterproctester.py')
67 assert_python_ok(script)
68
Christian Heimes4fbc72b2008-03-22 00:47:35 +000069
Brian Curtin3f004b12010-08-06 19:34:52 +000070@unittest.skipUnless(sys.platform == "win32", "Windows specific")
71class WindowsSignalTests(unittest.TestCase):
72 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +000073 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +000074 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +100075 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +000076 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
77 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
78 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +100079 # Set and then reset a handler for signals that work on windows.
80 # Issue #18396, only for signals without a C-level handler.
81 if signal.getsignal(sig) is not None:
82 signal.signal(sig, signal.signal(sig, handler))
83 checked.add(sig)
84 # Issue #18396: Ensure the above loop at least tested *something*
85 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +000086
87 with self.assertRaises(ValueError):
88 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +000089
90 with self.assertRaises(ValueError):
91 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +000092
93
Benjamin Petersonc68a4a02013-01-18 00:10:24 -050094class WakeupFDTests(unittest.TestCase):
95
96 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +020097 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +020098 self.assertRaises((ValueError, OSError),
99 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500100
Victor Stinner11517102014-07-29 23:31:34 +0200101 def test_invalid_socket(self):
102 sock = socket.socket()
103 fd = sock.fileno()
104 sock.close()
105 self.assertRaises((ValueError, OSError),
106 signal.set_wakeup_fd, fd)
107
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200108 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200109 r1, w1 = os.pipe()
110 self.addCleanup(os.close, r1)
111 self.addCleanup(os.close, w1)
112 r2, w2 = os.pipe()
113 self.addCleanup(os.close, r2)
114 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200115
Victor Stinner7cea44d2014-08-27 14:02:36 +0200116 if hasattr(os, 'set_blocking'):
117 os.set_blocking(w1, False)
118 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200119
Victor Stinner1d8948e2014-07-24 22:51:05 +0200120 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200121 self.assertEqual(signal.set_wakeup_fd(w2), w1)
122 self.assertEqual(signal.set_wakeup_fd(-1), w2)
123 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200124
Victor Stinner11517102014-07-29 23:31:34 +0200125 def test_set_wakeup_fd_socket_result(self):
126 sock1 = socket.socket()
127 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200128 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200129 fd1 = sock1.fileno()
130
131 sock2 = socket.socket()
132 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200133 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200134 fd2 = sock2.fileno()
135
136 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200137 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
138 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
139 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200140
Victor Stinner38227602014-08-27 12:59:44 +0200141 # On Windows, files are always blocking and Windows does not provide a
142 # function to test if a socket is in non-blocking mode.
143 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
144 def test_set_wakeup_fd_blocking(self):
145 rfd, wfd = os.pipe()
146 self.addCleanup(os.close, rfd)
147 self.addCleanup(os.close, wfd)
148
149 # fd must be non-blocking
150 os.set_blocking(wfd, True)
151 with self.assertRaises(ValueError) as cm:
152 signal.set_wakeup_fd(wfd)
153 self.assertEqual(str(cm.exception),
154 "the fd %s must be in non-blocking mode" % wfd)
155
156 # non-blocking is ok
157 os.set_blocking(wfd, False)
158 signal.set_wakeup_fd(wfd)
159 signal.set_wakeup_fd(-1)
160
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500161
Brian Curtin3f004b12010-08-06 19:34:52 +0000162@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000163class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200164 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200165 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200166 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200167 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200168 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200169 import os
170 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200171 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000172
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200173 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200174
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200175 def handler(signum, frame):
176 pass
177
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200178 def check_signum(signals):
179 data = os.read(read, len(signals)+1)
180 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200181 if not {!r}:
182 raised = set(raised)
183 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200184 if raised != signals:
185 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200186
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200187 {}
188
189 signal.signal(signal.SIGALRM, handler)
190 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200191 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200192 signal.set_wakeup_fd(write)
193
194 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200195 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200196
197 os.close(read)
198 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200199 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200200
201 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200202
Victor Stinner56e8c292014-07-21 12:30:22 +0200203 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200204 def test_wakeup_write_error(self):
205 # Issue #16105: write() errors in the C signal handler should not
206 # pass silently.
207 # Use a subprocess to have only one thread.
208 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200209 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200210 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200211 import os
212 import signal
213 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200214 from test.support import captured_stderr
215
216 def handler(signum, frame):
217 1/0
218
219 signal.signal(signal.SIGALRM, handler)
220 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200221 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200222
223 # Set wakeup_fd a read-only file descriptor to trigger the error
224 signal.set_wakeup_fd(r)
225 try:
226 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200227 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200228 except ZeroDivisionError:
229 # An ignored exception should have been printed out on stderr
230 err = err.getvalue()
231 if ('Exception ignored when trying to write to the signal wakeup fd'
232 not in err):
233 raise AssertionError(err)
234 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
235 raise AssertionError(err)
236 else:
237 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200238
239 os.close(r)
240 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200241 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200242 r, w = os.pipe()
243 try:
244 os.write(r, b'x')
245 except OSError:
246 pass
247 else:
248 self.skipTest("OS doesn't report write() error on the read end of a pipe")
249 finally:
250 os.close(r)
251 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200252
253 assert_python_ok('-c', code)
254
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000255 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200256 self.check_wakeup("""def test():
257 import select
258 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000259
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200260 TIMEOUT_FULL = 10
261 TIMEOUT_HALF = 5
262
Victor Stinner749a6a82015-03-30 22:09:14 +0200263 class InterruptSelect(Exception):
264 pass
265
266 def handler(signum, frame):
267 raise InterruptSelect
268 signal.signal(signal.SIGALRM, handler)
269
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200270 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100271
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200272 # We attempt to get a signal during the sleep,
273 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100274 try:
275 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200276 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100277 pass
278 else:
279 raise Exception("select() was not interrupted")
280
281 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200282 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100283 after_time = time.monotonic()
284 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200285 if dt >= TIMEOUT_HALF:
286 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200287 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000288
289 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200290 self.check_wakeup("""def test():
291 import select
292 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000293
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200294 TIMEOUT_FULL = 10
295 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000296
Victor Stinner749a6a82015-03-30 22:09:14 +0200297 class InterruptSelect(Exception):
298 pass
299
300 def handler(signum, frame):
301 raise InterruptSelect
302 signal.signal(signal.SIGALRM, handler)
303
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200304 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100305 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200306 # We attempt to get a signal during the select call
307 try:
308 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200309 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200310 pass
311 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200312 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100313 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200314 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():
Victor Stinner56e8c292014-07-21 12:30:22 +0200321 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200322 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200323 _testcapi.raise_signal(signal.SIGUSR1)
324 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200325 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000326
Victor Stinnerc13ef662011-05-25 02:35:58 +0200327 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
328 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200329 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200330 self.check_wakeup("""def test():
331 signum1 = signal.SIGUSR1
332 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200333
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200334 signal.signal(signum1, handler)
335 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200336
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200337 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200338 _testcapi.raise_signal(signum1)
339 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200340 # Unblocking the 2 signals calls the C signal handler twice
341 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200342 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200343
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000344
Victor Stinner11517102014-07-29 23:31:34 +0200345@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
346class WakeupSocketSignalTests(unittest.TestCase):
347
348 @unittest.skipIf(_testcapi is None, 'need _testcapi')
349 def test_socket(self):
350 # use a subprocess to have only one thread
351 code = """if 1:
352 import signal
353 import socket
354 import struct
355 import _testcapi
356
357 signum = signal.SIGINT
358 signals = (signum,)
359
360 def handler(signum, frame):
361 pass
362
363 signal.signal(signum, handler)
364
365 read, write = socket.socketpair()
366 read.setblocking(False)
367 write.setblocking(False)
368 signal.set_wakeup_fd(write.fileno())
369
370 _testcapi.raise_signal(signum)
371
372 data = read.recv(1)
373 if not data:
374 raise Exception("no signum written")
375 raised = struct.unpack('B', data)
376 if raised != signals:
377 raise Exception("%r != %r" % (raised, signals))
378
379 read.close()
380 write.close()
381 """
382
383 assert_python_ok('-c', code)
384
385 @unittest.skipIf(_testcapi is None, 'need _testcapi')
386 def test_send_error(self):
387 # Use a subprocess to have only one thread.
388 if os.name == 'nt':
389 action = 'send'
390 else:
391 action = 'write'
392 code = """if 1:
393 import errno
394 import signal
395 import socket
396 import sys
397 import time
398 import _testcapi
399 from test.support import captured_stderr
400
401 signum = signal.SIGINT
402
403 def handler(signum, frame):
404 pass
405
406 signal.signal(signum, handler)
407
408 read, write = socket.socketpair()
409 read.setblocking(False)
410 write.setblocking(False)
411
412 signal.set_wakeup_fd(write.fileno())
413
414 # Close sockets: send() will fail
415 read.close()
416 write.close()
417
418 with captured_stderr() as err:
419 _testcapi.raise_signal(signum)
420
421 err = err.getvalue()
422 if ('Exception ignored when trying to {action} to the signal wakeup fd'
423 not in err):
424 raise AssertionError(err)
425 """.format(action=action)
426 assert_python_ok('-c', code)
427
428
Brian Curtin3f004b12010-08-06 19:34:52 +0000429@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000430class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000431
Victor Stinnerd6284962011-06-20 23:28:09 +0200432 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000433 """Perform a read during which a signal will arrive. Return True if the
434 read is interrupted by the signal and raises an exception. Return False
435 if it returns normally.
436 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200437 # use a subprocess to have only one thread, to have a timeout on the
438 # blocking read and to not touch signal handling in this process
439 code = """if 1:
440 import errno
441 import os
442 import signal
443 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000444
Victor Stinnerd6284962011-06-20 23:28:09 +0200445 interrupt = %r
446 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000447
Victor Stinnerd6284962011-06-20 23:28:09 +0200448 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000449 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200450
451 signal.signal(signal.SIGALRM, handler)
452 if interrupt is not None:
453 signal.siginterrupt(signal.SIGALRM, interrupt)
454
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200455 print("ready")
456 sys.stdout.flush()
457
Victor Stinnerd6284962011-06-20 23:28:09 +0200458 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200459 try:
460 for loop in range(2):
461 # send a SIGALRM in a second (during the read)
462 signal.alarm(1)
463 try:
464 # blocking call: read from a pipe without data
465 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000466 except ZeroDivisionError:
467 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200468 else:
469 sys.exit(2)
470 sys.exit(3)
471 finally:
472 os.close(r)
473 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200474 """ % (interrupt,)
475 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000476 try:
Victor Stinner45273652011-06-22 22:15:51 +0200477 # wait until the child process is loaded and has started
478 first_line = process.stdout.readline()
479
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200480 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200481 except subprocess.TimeoutExpired:
482 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000483 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200484 else:
Victor Stinner45273652011-06-22 22:15:51 +0200485 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200486 exitcode = process.wait()
487 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200488 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200489 % (exitcode, stdout))
490 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000491
492 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200493 # If a signal handler is installed and siginterrupt is not called
494 # at all, when that signal arrives, it interrupts a syscall that's in
495 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200496 interrupted = self.readpipe_interrupted(None)
497 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000498
499 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200500 # If a signal handler is installed and siginterrupt is called with
501 # a true value for the second argument, when that signal arrives, it
502 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200503 interrupted = self.readpipe_interrupted(True)
504 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000505
506 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200507 # If a signal handler is installed and siginterrupt is called with
508 # a false value for the second argument, when that signal arrives, it
509 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200510 interrupted = self.readpipe_interrupted(False)
511 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000512
513
Brian Curtin3f004b12010-08-06 19:34:52 +0000514@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000515class ItimerTest(unittest.TestCase):
516 def setUp(self):
517 self.hndl_called = False
518 self.hndl_count = 0
519 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000520 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000521
522 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000523 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000524 if self.itimer is not None: # test_itimer_exc doesn't change this attr
525 # just ensure that itimer is stopped
526 signal.setitimer(self.itimer, 0)
527
528 def sig_alrm(self, *args):
529 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000530
531 def sig_vtalrm(self, *args):
532 self.hndl_called = True
533
534 if self.hndl_count > 3:
535 # it shouldn't be here, because it should have been disabled.
536 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
537 "timer.")
538 elif self.hndl_count == 3:
539 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
540 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000541
542 self.hndl_count += 1
543
Martin v. Löwis823725e2008-03-24 13:39:54 +0000544 def sig_prof(self, *args):
545 self.hndl_called = True
546 signal.setitimer(signal.ITIMER_PROF, 0)
547
Martin v. Löwis823725e2008-03-24 13:39:54 +0000548 def test_itimer_exc(self):
549 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
550 # defines it ?
551 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000552 # Negative times are treated as zero on some platforms.
553 if 0:
554 self.assertRaises(signal.ItimerError,
555 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000556
557 def test_itimer_real(self):
558 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000559 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000560 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000561 self.assertEqual(self.hndl_called, True)
562
R. David Murray44546f82010-04-21 01:59:28 +0000563 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000564 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
565 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000566 def test_itimer_virtual(self):
567 self.itimer = signal.ITIMER_VIRTUAL
568 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
569 signal.setitimer(self.itimer, 0.3, 0.2)
570
Victor Stinner79d68f92015-03-19 21:54:09 +0100571 start_time = time.monotonic()
572 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000573 # use up some virtual time by doing real work
574 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000575 if signal.getitimer(self.itimer) == (0.0, 0.0):
576 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000577 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000578 self.skipTest("timeout: likely cause: machine too slow or load too "
579 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000580
581 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000582 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000583 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000584 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000585
R. David Murray44546f82010-04-21 01:59:28 +0000586 # Issue 3864, unknown if this affects earlier versions of freebsd also
587 @unittest.skipIf(sys.platform=='freebsd6',
588 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000589 def test_itimer_prof(self):
590 self.itimer = signal.ITIMER_PROF
591 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000592 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000593
Victor Stinner79d68f92015-03-19 21:54:09 +0100594 start_time = time.monotonic()
595 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000596 # do some work
597 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000598 if signal.getitimer(self.itimer) == (0.0, 0.0):
599 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000600 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000601 self.skipTest("timeout: likely cause: machine too slow or load too "
602 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000603
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000604 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000605 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000606 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000607 self.assertEqual(self.hndl_called, True)
608
Victor Stinnera9293352011-04-30 15:21:58 +0200609
Victor Stinner35b300c2011-05-04 13:20:35 +0200610class PendingSignalsTests(unittest.TestCase):
611 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200612 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
613 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200614 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200615 @unittest.skipUnless(hasattr(signal, 'sigpending'),
616 'need signal.sigpending()')
617 def test_sigpending_empty(self):
618 self.assertEqual(signal.sigpending(), set())
619
620 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
621 'need signal.pthread_sigmask()')
622 @unittest.skipUnless(hasattr(signal, 'sigpending'),
623 'need signal.sigpending()')
624 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200625 code = """if 1:
626 import os
627 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200628
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200629 def handler(signum, frame):
630 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200631
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200632 signum = signal.SIGUSR1
633 signal.signal(signum, handler)
634
635 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
636 os.kill(os.getpid(), signum)
637 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200638 for sig in pending:
639 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200640 if pending != {signum}:
641 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200642 try:
643 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
644 except ZeroDivisionError:
645 pass
646 else:
647 raise Exception("ZeroDivisionError not raised")
648 """
649 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200650
651 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
652 'need signal.pthread_kill()')
653 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200654 code = """if 1:
655 import signal
656 import threading
657 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200658
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200659 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200660
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200661 def handler(signum, frame):
662 1/0
663
664 signal.signal(signum, handler)
665
666 if sys.platform == 'freebsd6':
667 # Issue #12392 and #12469: send a signal to the main thread
668 # doesn't work before the creation of the first thread on
669 # FreeBSD 6
670 def noop():
671 pass
672 thread = threading.Thread(target=noop)
673 thread.start()
674 thread.join()
675
676 tid = threading.get_ident()
677 try:
678 signal.pthread_kill(tid, signum)
679 except ZeroDivisionError:
680 pass
681 else:
682 raise Exception("ZeroDivisionError not raised")
683 """
684 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200685
Victor Stinner7f294d12011-06-10 14:02:10 +0200686 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
687 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200688 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200689 """
690 test: body of the "def test(signum):" function.
691 blocked: number of the blocked signal
692 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200693 code = '''if 1:
694 import signal
695 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200696 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200697
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200698 def handler(signum, frame):
699 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200700
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200701 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200702
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200703 blocked = %s
704 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200705
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200706 # child: block and wait the signal
707 try:
708 signal.signal(signum, handler)
709 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200710
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200711 # Do the tests
712 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200713
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200714 # The handler must not be called on unblock
715 try:
716 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
717 except ZeroDivisionError:
718 print("the signal handler has been called",
719 file=sys.stderr)
720 sys.exit(1)
721 except BaseException as err:
722 print("error: {}".format(err), file=sys.stderr)
723 sys.stderr.flush()
724 sys.exit(1)
725 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200726
Ross Lagerwallbc808222011-06-25 12:13:40 +0200727 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200728 # process might have several threads running, use a subprocess to have
729 # a single thread.
730 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200731
Victor Stinnerb3e72192011-05-08 01:46:11 +0200732 @unittest.skipUnless(hasattr(signal, 'sigwait'),
733 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200734 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200735 self.wait_helper(signal.SIGALRM, '''
736 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200737 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200738 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200739 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200740 if received != signum:
741 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200742 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200743
744 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
745 'need signal.sigwaitinfo()')
746 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200747 self.wait_helper(signal.SIGALRM, '''
748 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200749 signal.alarm(1)
750 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200751 if info.si_signo != signum:
752 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200753 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200754
755 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
756 'need signal.sigtimedwait()')
757 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200758 self.wait_helper(signal.SIGALRM, '''
759 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200760 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100761 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200762 if info.si_signo != signum:
763 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200764 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200765
Ross Lagerwallbc808222011-06-25 12:13:40 +0200766 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
767 'need signal.sigtimedwait()')
768 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200769 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200770 self.wait_helper(signal.SIGALRM, '''
771 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200772 import os
773 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100774 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200775 if info.si_signo != signum:
776 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200777 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200778
779 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
780 'need signal.sigtimedwait()')
781 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200782 self.wait_helper(signal.SIGALRM, '''
783 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100784 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200785 if received is not None:
786 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200787 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200788
789 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
790 'need signal.sigtimedwait()')
791 def test_sigtimedwait_negative_timeout(self):
792 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100793 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200794
Ross Lagerwallbc808222011-06-25 12:13:40 +0200795 @unittest.skipUnless(hasattr(signal, 'sigwait'),
796 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200797 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
798 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200799 @unittest.skipIf(threading is None, "test needs threading module")
800 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200801 # Check that calling sigwait() from a thread doesn't suspend the whole
802 # process. A new interpreter is spawned to avoid problems when mixing
803 # threads and fork(): only async-safe functions are allowed between
804 # fork() and exec().
805 assert_python_ok("-c", """if True:
806 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200807
Victor Stinner415007e2011-06-13 16:19:06 +0200808 # the default handler terminates the process
809 signum = signal.SIGUSR1
810
811 def kill_later():
812 # wait until the main thread is waiting in sigwait()
813 time.sleep(1)
814 os.kill(os.getpid(), signum)
815
816 # the signal must be blocked by all the threads
817 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
818 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200819 killer.start()
820 received = signal.sigwait([signum])
821 if received != signum:
822 print("sigwait() received %s, not %s" % (received, signum),
823 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200824 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200825 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200826 # unblock the signal, which should have been cleared by sigwait()
827 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
828 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200829
Victor Stinnerb3e72192011-05-08 01:46:11 +0200830 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
831 'need signal.pthread_sigmask()')
832 def test_pthread_sigmask_arguments(self):
833 self.assertRaises(TypeError, signal.pthread_sigmask)
834 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
835 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
836 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
837
838 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
839 'need signal.pthread_sigmask()')
840 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200841 code = """if 1:
842 import signal
843 import os; import threading
844
845 def handler(signum, frame):
846 1/0
847
848 def kill(signum):
849 os.kill(os.getpid(), signum)
850
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200851 def check_mask(mask):
852 for sig in mask:
853 assert isinstance(sig, signal.Signals), repr(sig)
854
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200855 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200856 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
857 check_mask(sigmask)
858 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200859
Victor Stinnerb3e72192011-05-08 01:46:11 +0200860 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200861
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200862 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200863 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200864
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200865 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200866 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200867 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200868 try:
869 kill(signum)
870 except ZeroDivisionError:
871 pass
872 else:
873 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200874
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200875 # Block and then raise SIGUSR1. The signal is blocked: the signal
876 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200877 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
878 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200879 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200880
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200881 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200882 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200883 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +0200884 if signum not in blocked:
885 raise Exception("%s not in %s" % (signum, blocked))
886 if old_mask ^ blocked != {signum}:
887 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200888
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200889 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200890 try:
R David Murrayfc069992013-12-13 20:52:19 -0500891 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200892 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200893 except ZeroDivisionError:
894 pass
895 else:
896 raise Exception("ZeroDivisionError not raised")
897 try:
898 kill(signum)
899 except ZeroDivisionError:
900 pass
901 else:
902 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200903
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200904 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200905 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200906 if signum in unblocked:
907 raise Exception("%s in %s" % (signum, unblocked))
908 if blocked ^ unblocked != {signum}:
909 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
910 if old_mask != unblocked:
911 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200912 """
913 assert_python_ok('-c', code)
914
915 @unittest.skipIf(sys.platform == 'freebsd6',
916 "issue #12392: send a signal to the main thread doesn't work "
917 "before the creation of the first thread on FreeBSD 6")
918 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
919 'need signal.pthread_kill()')
920 def test_pthread_kill_main_thread(self):
921 # Test that a signal can be sent to the main thread with pthread_kill()
922 # before any other thread has been created (see issue #12392).
923 code = """if True:
924 import threading
925 import signal
926 import sys
927
928 def handler(signum, frame):
929 sys.exit(3)
930
931 signal.signal(signal.SIGUSR1, handler)
932 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
933 sys.exit(2)
934 """
935
936 with spawn_python('-c', code) as process:
937 stdout, stderr = process.communicate()
938 exitcode = process.wait()
939 if exitcode != 3:
940 raise Exception("Child error (exit code %s): %s" %
941 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200942
943
Zachary Ware38c707e2015-04-13 15:00:43 -0500944def tearDownModule():
945 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000946
947if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500948 unittest.main()