blob: 2a6217ef64326892a8853755f288c4fd55e13d14 [file] [log] [blame]
Vladimir Matveevc24c6c22019-01-08 01:58:25 -08001import errno
Victor Stinnerd6debb22017-03-27 16:05:26 +02002import os
Antoine Pitrouc08177a2017-06-28 23:29:29 +02003import random
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00004import signal
Victor Stinner11517102014-07-29 23:31:34 +02005import socket
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02006import statistics
Christian Heimes4fbc72b2008-03-22 00:47:35 +00007import subprocess
Victor Stinnerd6debb22017-03-27 16:05:26 +02008import sys
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02009import threading
Victor Stinnerd6debb22017-03-27 16:05:26 +020010import time
11import unittest
12from test import support
Berker Peksagce643912015-05-06 06:33:17 +030013from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020014try:
Victor Stinner56e8c292014-07-21 12:30:22 +020015 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
22 def test_enums(self):
23 for name in dir(signal):
24 sig = getattr(signal, name)
25 if name in {'SIG_DFL', 'SIG_IGN'}:
26 self.assertIsInstance(sig, signal.Handlers)
27 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
28 self.assertIsInstance(sig, signal.Sigmasks)
29 elif name.startswith('SIG') and not name.startswith('SIG_'):
30 self.assertIsInstance(sig, signal.Signals)
31 elif name.startswith('CTRL_'):
32 self.assertIsInstance(sig, signal.Signals)
33 self.assertEqual(sys.platform, "win32")
34
35
Brian Curtin3f004b12010-08-06 19:34:52 +000036@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +020037class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +000038 def trivial_signal_handler(self, *args):
39 pass
40
Thomas Woutersed03b412007-08-28 21:37:11 +000041 def test_out_of_range_signal_number_raises_error(self):
42 self.assertRaises(ValueError, signal.getsignal, 4242)
43
Thomas Woutersed03b412007-08-28 21:37:11 +000044 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +000045 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +000046
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010047 self.assertRaises(ValueError, signal.strsignal, 4242)
48
Thomas Woutersed03b412007-08-28 21:37:11 +000049 def test_setting_signal_handler_to_none_raises_error(self):
50 self.assertRaises(TypeError, signal.signal,
51 signal.SIGUSR1, None)
52
Christian Heimes4fbc72b2008-03-22 00:47:35 +000053 def test_getsignal(self):
54 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020055 self.assertIsInstance(hup, signal.Handlers)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000056 self.assertEqual(signal.getsignal(signal.SIGHUP),
57 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000058 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000059 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000060
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010061 def test_strsignal(self):
Antoine Pietri019f5b32018-03-12 20:03:14 +010062 self.assertIn("Interrupt", signal.strsignal(signal.SIGINT))
63 self.assertIn("Terminated", signal.strsignal(signal.SIGTERM))
Michael Osipov48ce4892018-08-23 15:27:19 +020064 self.assertIn("Hangup", signal.strsignal(signal.SIGHUP))
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010065
Victor Stinner32eb8402016-03-15 11:12:35 +010066 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner32eb8402016-03-15 11:12:35 +010067 def test_interprocess_signal(self):
68 dirname = os.path.dirname(__file__)
69 script = os.path.join(dirname, 'signalinterproctester.py')
70 assert_python_ok(script)
71
Antoine Pitrou9d3627e2018-05-04 13:00:50 +020072 def test_valid_signals(self):
73 s = signal.valid_signals()
74 self.assertIsInstance(s, set)
75 self.assertIn(signal.Signals.SIGINT, s)
76 self.assertIn(signal.Signals.SIGALRM, s)
77 self.assertNotIn(0, s)
78 self.assertNotIn(signal.NSIG, s)
79 self.assertLess(len(s), signal.NSIG)
80
Christian Heimes4fbc72b2008-03-22 00:47:35 +000081
Brian Curtin3f004b12010-08-06 19:34:52 +000082@unittest.skipUnless(sys.platform == "win32", "Windows specific")
83class WindowsSignalTests(unittest.TestCase):
Antoine Pitrou9d3627e2018-05-04 13:00:50 +020084
85 def test_valid_signals(self):
86 s = signal.valid_signals()
87 self.assertIsInstance(s, set)
88 self.assertGreaterEqual(len(s), 6)
89 self.assertIn(signal.Signals.SIGINT, s)
90 self.assertNotIn(0, s)
91 self.assertNotIn(signal.NSIG, s)
92 self.assertLess(len(s), signal.NSIG)
93
Brian Curtin3f004b12010-08-06 19:34:52 +000094 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +000095 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +000096 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +100097 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +000098 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
99 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
100 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000101 # Set and then reset a handler for signals that work on windows.
102 # Issue #18396, only for signals without a C-level handler.
103 if signal.getsignal(sig) is not None:
104 signal.signal(sig, signal.signal(sig, handler))
105 checked.add(sig)
106 # Issue #18396: Ensure the above loop at least tested *something*
107 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +0000108
109 with self.assertRaises(ValueError):
110 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000111
112 with self.assertRaises(ValueError):
113 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000114
115
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500116class WakeupFDTests(unittest.TestCase):
117
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800118 def test_invalid_call(self):
119 # First parameter is positional-only
120 with self.assertRaises(TypeError):
121 signal.set_wakeup_fd(signum=signal.SIGINT)
122
123 # warn_on_full_buffer is a keyword-only parameter
124 with self.assertRaises(TypeError):
125 signal.set_wakeup_fd(signal.SIGINT, False)
126
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500127 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200128 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +0200129 self.assertRaises((ValueError, OSError),
130 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500131
Victor Stinner11517102014-07-29 23:31:34 +0200132 def test_invalid_socket(self):
133 sock = socket.socket()
134 fd = sock.fileno()
135 sock.close()
136 self.assertRaises((ValueError, OSError),
137 signal.set_wakeup_fd, fd)
138
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200139 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200140 r1, w1 = os.pipe()
141 self.addCleanup(os.close, r1)
142 self.addCleanup(os.close, w1)
143 r2, w2 = os.pipe()
144 self.addCleanup(os.close, r2)
145 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200146
Victor Stinner7cea44d2014-08-27 14:02:36 +0200147 if hasattr(os, 'set_blocking'):
148 os.set_blocking(w1, False)
149 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200150
Victor Stinner1d8948e2014-07-24 22:51:05 +0200151 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200152 self.assertEqual(signal.set_wakeup_fd(w2), w1)
153 self.assertEqual(signal.set_wakeup_fd(-1), w2)
154 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200155
Victor Stinner11517102014-07-29 23:31:34 +0200156 def test_set_wakeup_fd_socket_result(self):
157 sock1 = socket.socket()
158 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200159 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200160 fd1 = sock1.fileno()
161
162 sock2 = socket.socket()
163 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200164 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200165 fd2 = sock2.fileno()
166
167 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200168 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
169 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
170 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200171
Victor Stinner38227602014-08-27 12:59:44 +0200172 # On Windows, files are always blocking and Windows does not provide a
173 # function to test if a socket is in non-blocking mode.
174 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
175 def test_set_wakeup_fd_blocking(self):
176 rfd, wfd = os.pipe()
177 self.addCleanup(os.close, rfd)
178 self.addCleanup(os.close, wfd)
179
180 # fd must be non-blocking
181 os.set_blocking(wfd, True)
182 with self.assertRaises(ValueError) as cm:
183 signal.set_wakeup_fd(wfd)
184 self.assertEqual(str(cm.exception),
185 "the fd %s must be in non-blocking mode" % wfd)
186
187 # non-blocking is ok
188 os.set_blocking(wfd, False)
189 signal.set_wakeup_fd(wfd)
190 signal.set_wakeup_fd(-1)
191
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500192
Brian Curtin3f004b12010-08-06 19:34:52 +0000193@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000194class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200195 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200196 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200197 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200198 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200199 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200200 import os
201 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200202 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000203
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200204 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200205
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200206 def handler(signum, frame):
207 pass
208
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200209 def check_signum(signals):
210 data = os.read(read, len(signals)+1)
211 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200212 if not {!r}:
213 raised = set(raised)
214 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200215 if raised != signals:
216 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200217
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200218 {}
219
220 signal.signal(signal.SIGALRM, handler)
221 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200222 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200223 signal.set_wakeup_fd(write)
224
225 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200226 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200227
228 os.close(read)
229 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200230 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200231
232 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200233
Victor Stinner56e8c292014-07-21 12:30:22 +0200234 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200235 def test_wakeup_write_error(self):
236 # Issue #16105: write() errors in the C signal handler should not
237 # pass silently.
238 # Use a subprocess to have only one thread.
239 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200240 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200241 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200242 import os
243 import signal
244 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200245 from test.support import captured_stderr
246
247 def handler(signum, frame):
248 1/0
249
250 signal.signal(signal.SIGALRM, handler)
251 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200252 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200253
254 # Set wakeup_fd a read-only file descriptor to trigger the error
255 signal.set_wakeup_fd(r)
256 try:
257 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800258 signal.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200259 except ZeroDivisionError:
260 # An ignored exception should have been printed out on stderr
261 err = err.getvalue()
262 if ('Exception ignored when trying to write to the signal wakeup fd'
263 not in err):
264 raise AssertionError(err)
265 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
266 raise AssertionError(err)
267 else:
268 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200269
270 os.close(r)
271 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200272 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200273 r, w = os.pipe()
274 try:
275 os.write(r, b'x')
276 except OSError:
277 pass
278 else:
279 self.skipTest("OS doesn't report write() error on the read end of a pipe")
280 finally:
281 os.close(r)
282 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200283
284 assert_python_ok('-c', code)
285
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000286 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200287 self.check_wakeup("""def test():
288 import select
289 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000290
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200291 TIMEOUT_FULL = 10
292 TIMEOUT_HALF = 5
293
Victor Stinner749a6a82015-03-30 22:09:14 +0200294 class InterruptSelect(Exception):
295 pass
296
297 def handler(signum, frame):
298 raise InterruptSelect
299 signal.signal(signal.SIGALRM, handler)
300
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200301 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100302
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200303 # We attempt to get a signal during the sleep,
304 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100305 try:
306 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200307 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100308 pass
309 else:
310 raise Exception("select() was not interrupted")
311
312 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200313 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100314 after_time = time.monotonic()
315 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200316 if dt >= TIMEOUT_HALF:
317 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200318 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000319
320 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200321 self.check_wakeup("""def test():
322 import select
323 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000324
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200325 TIMEOUT_FULL = 10
326 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000327
Victor Stinner749a6a82015-03-30 22:09:14 +0200328 class InterruptSelect(Exception):
329 pass
330
331 def handler(signum, frame):
332 raise InterruptSelect
333 signal.signal(signal.SIGALRM, handler)
334
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200335 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100336 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200337 # We attempt to get a signal during the select call
338 try:
339 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200340 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200341 pass
342 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200343 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100344 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200345 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200346 if dt >= TIMEOUT_HALF:
347 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200348 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200349
350 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200351 self.check_wakeup("""def test():
352 signal.signal(signal.SIGUSR1, handler)
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800353 signal.raise_signal(signal.SIGUSR1)
354 signal.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200355 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000356
Victor Stinnerc13ef662011-05-25 02:35:58 +0200357 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
358 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200359 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200360 self.check_wakeup("""def test():
361 signum1 = signal.SIGUSR1
362 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200363
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200364 signal.signal(signum1, handler)
365 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200366
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200367 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800368 signal.raise_signal(signum1)
369 signal.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200370 # Unblocking the 2 signals calls the C signal handler twice
371 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200372 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200373
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000374
Victor Stinner11517102014-07-29 23:31:34 +0200375@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
376class WakeupSocketSignalTests(unittest.TestCase):
377
378 @unittest.skipIf(_testcapi is None, 'need _testcapi')
379 def test_socket(self):
380 # use a subprocess to have only one thread
381 code = """if 1:
382 import signal
383 import socket
384 import struct
385 import _testcapi
386
387 signum = signal.SIGINT
388 signals = (signum,)
389
390 def handler(signum, frame):
391 pass
392
393 signal.signal(signum, handler)
394
395 read, write = socket.socketpair()
Victor Stinner11517102014-07-29 23:31:34 +0200396 write.setblocking(False)
397 signal.set_wakeup_fd(write.fileno())
398
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800399 signal.raise_signal(signum)
Victor Stinner11517102014-07-29 23:31:34 +0200400
401 data = read.recv(1)
402 if not data:
403 raise Exception("no signum written")
404 raised = struct.unpack('B', data)
405 if raised != signals:
406 raise Exception("%r != %r" % (raised, signals))
407
408 read.close()
409 write.close()
410 """
411
412 assert_python_ok('-c', code)
413
414 @unittest.skipIf(_testcapi is None, 'need _testcapi')
415 def test_send_error(self):
416 # Use a subprocess to have only one thread.
417 if os.name == 'nt':
418 action = 'send'
419 else:
420 action = 'write'
421 code = """if 1:
422 import errno
423 import signal
424 import socket
425 import sys
426 import time
427 import _testcapi
428 from test.support import captured_stderr
429
430 signum = signal.SIGINT
431
432 def handler(signum, frame):
433 pass
434
435 signal.signal(signum, handler)
436
437 read, write = socket.socketpair()
438 read.setblocking(False)
439 write.setblocking(False)
440
441 signal.set_wakeup_fd(write.fileno())
442
443 # Close sockets: send() will fail
444 read.close()
445 write.close()
446
447 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800448 signal.raise_signal(signum)
Victor Stinner11517102014-07-29 23:31:34 +0200449
450 err = err.getvalue()
451 if ('Exception ignored when trying to {action} to the signal wakeup fd'
452 not in err):
453 raise AssertionError(err)
454 """.format(action=action)
455 assert_python_ok('-c', code)
456
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800457 @unittest.skipIf(_testcapi is None, 'need _testcapi')
458 def test_warn_on_full_buffer(self):
459 # Use a subprocess to have only one thread.
460 if os.name == 'nt':
461 action = 'send'
462 else:
463 action = 'write'
464 code = """if 1:
465 import errno
466 import signal
467 import socket
468 import sys
469 import time
470 import _testcapi
471 from test.support import captured_stderr
472
473 signum = signal.SIGINT
474
475 # This handler will be called, but we intentionally won't read from
476 # the wakeup fd.
477 def handler(signum, frame):
478 pass
479
480 signal.signal(signum, handler)
481
482 read, write = socket.socketpair()
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800483
Victor Stinner686b4b52018-07-18 18:29:54 +0200484 # Fill the socketpair buffer
485 if sys.platform == 'win32':
486 # bpo-34130: On Windows, sometimes non-blocking send fails to fill
487 # the full socketpair buffer, so use a timeout of 50 ms instead.
488 write.settimeout(0.050)
489 else:
490 write.setblocking(False)
491
492 # Start with large chunk size to reduce the
493 # number of send needed to fill the buffer.
494 written = 0
495 for chunk_size in (2 ** 16, 2 ** 8, 1):
496 chunk = b"x" * chunk_size
497 try:
498 while True:
499 write.send(chunk)
500 written += chunk_size
501 except (BlockingIOError, socket.timeout):
502 pass
503
504 print(f"%s bytes written into the socketpair" % written, flush=True)
505
506 write.setblocking(False)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800507 try:
Victor Stinner686b4b52018-07-18 18:29:54 +0200508 write.send(b"x")
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800509 except BlockingIOError:
Victor Stinner686b4b52018-07-18 18:29:54 +0200510 # The socketpair buffer seems full
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800511 pass
Victor Stinner686b4b52018-07-18 18:29:54 +0200512 else:
513 raise AssertionError("%s bytes failed to fill the socketpair "
514 "buffer" % written)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800515
516 # By default, we get a warning when a signal arrives
Victor Stinner686b4b52018-07-18 18:29:54 +0200517 msg = ('Exception ignored when trying to {action} '
518 'to the signal wakeup fd')
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800519 signal.set_wakeup_fd(write.fileno())
520
521 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800522 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800523
524 err = err.getvalue()
Victor Stinner686b4b52018-07-18 18:29:54 +0200525 if msg not in err:
526 raise AssertionError("first set_wakeup_fd() test failed, "
527 "stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800528
529 # And also if warn_on_full_buffer=True
530 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=True)
531
532 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800533 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800534
535 err = err.getvalue()
Victor Stinner686b4b52018-07-18 18:29:54 +0200536 if msg not in err:
537 raise AssertionError("set_wakeup_fd(warn_on_full_buffer=True) "
538 "test failed, stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800539
540 # But not if warn_on_full_buffer=False
541 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=False)
542
543 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800544 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800545
546 err = err.getvalue()
547 if err != "":
Victor Stinner686b4b52018-07-18 18:29:54 +0200548 raise AssertionError("set_wakeup_fd(warn_on_full_buffer=False) "
549 "test failed, stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800550
551 # And then check the default again, to make sure warn_on_full_buffer
552 # settings don't leak across calls.
553 signal.set_wakeup_fd(write.fileno())
554
555 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800556 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800557
558 err = err.getvalue()
Victor Stinner686b4b52018-07-18 18:29:54 +0200559 if msg not in err:
560 raise AssertionError("second set_wakeup_fd() test failed, "
561 "stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800562
563 """.format(action=action)
564 assert_python_ok('-c', code)
565
Victor Stinner11517102014-07-29 23:31:34 +0200566
Brian Curtin3f004b12010-08-06 19:34:52 +0000567@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000568class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000569
Victor Stinnerd6284962011-06-20 23:28:09 +0200570 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000571 """Perform a read during which a signal will arrive. Return True if the
572 read is interrupted by the signal and raises an exception. Return False
573 if it returns normally.
574 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200575 # use a subprocess to have only one thread, to have a timeout on the
576 # blocking read and to not touch signal handling in this process
577 code = """if 1:
578 import errno
579 import os
580 import signal
581 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000582
Victor Stinnerd6284962011-06-20 23:28:09 +0200583 interrupt = %r
584 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000585
Victor Stinnerd6284962011-06-20 23:28:09 +0200586 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000587 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200588
589 signal.signal(signal.SIGALRM, handler)
590 if interrupt is not None:
591 signal.siginterrupt(signal.SIGALRM, interrupt)
592
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200593 print("ready")
594 sys.stdout.flush()
595
Victor Stinnerd6284962011-06-20 23:28:09 +0200596 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200597 try:
598 for loop in range(2):
599 # send a SIGALRM in a second (during the read)
600 signal.alarm(1)
601 try:
602 # blocking call: read from a pipe without data
603 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000604 except ZeroDivisionError:
605 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200606 else:
607 sys.exit(2)
608 sys.exit(3)
609 finally:
610 os.close(r)
611 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200612 """ % (interrupt,)
613 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000614 try:
Victor Stinner45273652011-06-22 22:15:51 +0200615 # wait until the child process is loaded and has started
616 first_line = process.stdout.readline()
617
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200618 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200619 except subprocess.TimeoutExpired:
620 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000621 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200622 else:
Victor Stinner45273652011-06-22 22:15:51 +0200623 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200624 exitcode = process.wait()
625 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200626 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200627 % (exitcode, stdout))
628 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000629
630 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200631 # If a signal handler is installed and siginterrupt is not called
632 # at all, when that signal arrives, it interrupts a syscall that's in
633 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200634 interrupted = self.readpipe_interrupted(None)
635 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000636
637 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200638 # If a signal handler is installed and siginterrupt is called with
639 # a true value for the second argument, when that signal arrives, it
640 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200641 interrupted = self.readpipe_interrupted(True)
642 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000643
644 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200645 # If a signal handler is installed and siginterrupt is called with
646 # a false value for the second argument, when that signal arrives, it
647 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200648 interrupted = self.readpipe_interrupted(False)
649 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000650
651
Brian Curtin3f004b12010-08-06 19:34:52 +0000652@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000653class ItimerTest(unittest.TestCase):
654 def setUp(self):
655 self.hndl_called = False
656 self.hndl_count = 0
657 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000658 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000659
660 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000661 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000662 if self.itimer is not None: # test_itimer_exc doesn't change this attr
663 # just ensure that itimer is stopped
664 signal.setitimer(self.itimer, 0)
665
666 def sig_alrm(self, *args):
667 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000668
669 def sig_vtalrm(self, *args):
670 self.hndl_called = True
671
672 if self.hndl_count > 3:
673 # it shouldn't be here, because it should have been disabled.
674 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
675 "timer.")
676 elif self.hndl_count == 3:
677 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
678 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000679
680 self.hndl_count += 1
681
Martin v. Löwis823725e2008-03-24 13:39:54 +0000682 def sig_prof(self, *args):
683 self.hndl_called = True
684 signal.setitimer(signal.ITIMER_PROF, 0)
685
Martin v. Löwis823725e2008-03-24 13:39:54 +0000686 def test_itimer_exc(self):
687 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
688 # defines it ?
689 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000690 # Negative times are treated as zero on some platforms.
691 if 0:
692 self.assertRaises(signal.ItimerError,
693 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000694
695 def test_itimer_real(self):
696 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000697 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000698 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000699 self.assertEqual(self.hndl_called, True)
700
R. David Murray44546f82010-04-21 01:59:28 +0000701 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner13ff2452018-01-22 18:32:50 +0100702 @unittest.skipIf(sys.platform in ('netbsd5',),
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000703 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000704 def test_itimer_virtual(self):
705 self.itimer = signal.ITIMER_VIRTUAL
706 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
707 signal.setitimer(self.itimer, 0.3, 0.2)
708
Victor Stinner79d68f92015-03-19 21:54:09 +0100709 start_time = time.monotonic()
710 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000711 # use up some virtual time by doing real work
712 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000713 if signal.getitimer(self.itimer) == (0.0, 0.0):
714 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000715 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000716 self.skipTest("timeout: likely cause: machine too slow or load too "
717 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000718
719 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000720 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000721 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000722 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000723
724 def test_itimer_prof(self):
725 self.itimer = signal.ITIMER_PROF
726 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000727 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000728
Victor Stinner79d68f92015-03-19 21:54:09 +0100729 start_time = time.monotonic()
730 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000731 # do some work
732 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000733 if signal.getitimer(self.itimer) == (0.0, 0.0):
734 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000735 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000736 self.skipTest("timeout: likely cause: machine too slow or load too "
737 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000738
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000739 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000740 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000741 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000742 self.assertEqual(self.hndl_called, True)
743
Antoine Pitrou729780a2017-06-30 10:01:05 +0200744 def test_setitimer_tiny(self):
745 # bpo-30807: C setitimer() takes a microsecond-resolution interval.
746 # Check that float -> timeval conversion doesn't round
747 # the interval down to zero, which would disable the timer.
748 self.itimer = signal.ITIMER_REAL
749 signal.setitimer(self.itimer, 1e-6)
750 time.sleep(1)
751 self.assertEqual(self.hndl_called, True)
752
Victor Stinnera9293352011-04-30 15:21:58 +0200753
Victor Stinner35b300c2011-05-04 13:20:35 +0200754class PendingSignalsTests(unittest.TestCase):
755 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200756 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
757 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200758 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200759 @unittest.skipUnless(hasattr(signal, 'sigpending'),
760 'need signal.sigpending()')
761 def test_sigpending_empty(self):
762 self.assertEqual(signal.sigpending(), set())
763
764 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
765 'need signal.pthread_sigmask()')
766 @unittest.skipUnless(hasattr(signal, 'sigpending'),
767 'need signal.sigpending()')
768 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200769 code = """if 1:
770 import os
771 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200772
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200773 def handler(signum, frame):
774 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200775
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200776 signum = signal.SIGUSR1
777 signal.signal(signum, handler)
778
779 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
780 os.kill(os.getpid(), signum)
781 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200782 for sig in pending:
783 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200784 if pending != {signum}:
785 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200786 try:
787 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
788 except ZeroDivisionError:
789 pass
790 else:
791 raise Exception("ZeroDivisionError not raised")
792 """
793 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200794
795 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
796 'need signal.pthread_kill()')
797 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200798 code = """if 1:
799 import signal
800 import threading
801 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200802
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200803 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200804
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200805 def handler(signum, frame):
806 1/0
807
808 signal.signal(signum, handler)
809
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200810 tid = threading.get_ident()
811 try:
812 signal.pthread_kill(tid, signum)
813 except ZeroDivisionError:
814 pass
815 else:
816 raise Exception("ZeroDivisionError not raised")
817 """
818 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200819
Victor Stinner7f294d12011-06-10 14:02:10 +0200820 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
821 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200822 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200823 """
824 test: body of the "def test(signum):" function.
825 blocked: number of the blocked signal
826 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200827 code = '''if 1:
828 import signal
829 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200830 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200831
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200832 def handler(signum, frame):
833 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200834
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200835 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200836
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200837 blocked = %s
838 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200839
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200840 # child: block and wait the signal
841 try:
842 signal.signal(signum, handler)
843 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200844
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200845 # Do the tests
846 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200847
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200848 # The handler must not be called on unblock
849 try:
850 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
851 except ZeroDivisionError:
852 print("the signal handler has been called",
853 file=sys.stderr)
854 sys.exit(1)
855 except BaseException as err:
856 print("error: {}".format(err), file=sys.stderr)
857 sys.stderr.flush()
858 sys.exit(1)
859 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200860
Ross Lagerwallbc808222011-06-25 12:13:40 +0200861 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200862 # process might have several threads running, use a subprocess to have
863 # a single thread.
864 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200865
Victor Stinnerb3e72192011-05-08 01:46:11 +0200866 @unittest.skipUnless(hasattr(signal, 'sigwait'),
867 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200868 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200869 self.wait_helper(signal.SIGALRM, '''
870 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200871 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200872 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200873 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200874 if received != signum:
875 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200876 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200877
878 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
879 'need signal.sigwaitinfo()')
880 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200881 self.wait_helper(signal.SIGALRM, '''
882 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200883 signal.alarm(1)
884 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200885 if info.si_signo != signum:
886 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200887 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200888
889 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
890 'need signal.sigtimedwait()')
891 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200892 self.wait_helper(signal.SIGALRM, '''
893 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200894 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100895 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200896 if info.si_signo != signum:
897 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200898 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200899
Ross Lagerwallbc808222011-06-25 12:13:40 +0200900 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
901 'need signal.sigtimedwait()')
902 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200903 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200904 self.wait_helper(signal.SIGALRM, '''
905 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200906 import os
907 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100908 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200909 if info.si_signo != signum:
910 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200911 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200912
913 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
914 'need signal.sigtimedwait()')
915 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200916 self.wait_helper(signal.SIGALRM, '''
917 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100918 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200919 if received is not None:
920 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200921 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200922
923 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
924 'need signal.sigtimedwait()')
925 def test_sigtimedwait_negative_timeout(self):
926 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100927 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200928
Ross Lagerwallbc808222011-06-25 12:13:40 +0200929 @unittest.skipUnless(hasattr(signal, 'sigwait'),
930 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200931 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
932 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200933 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200934 # Check that calling sigwait() from a thread doesn't suspend the whole
935 # process. A new interpreter is spawned to avoid problems when mixing
936 # threads and fork(): only async-safe functions are allowed between
937 # fork() and exec().
938 assert_python_ok("-c", """if True:
939 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200940
Victor Stinner415007e2011-06-13 16:19:06 +0200941 # the default handler terminates the process
942 signum = signal.SIGUSR1
943
944 def kill_later():
945 # wait until the main thread is waiting in sigwait()
946 time.sleep(1)
947 os.kill(os.getpid(), signum)
948
949 # the signal must be blocked by all the threads
950 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
951 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200952 killer.start()
953 received = signal.sigwait([signum])
954 if received != signum:
955 print("sigwait() received %s, not %s" % (received, signum),
956 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200957 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200958 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200959 # unblock the signal, which should have been cleared by sigwait()
960 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
961 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200962
Victor Stinnerb3e72192011-05-08 01:46:11 +0200963 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
964 'need signal.pthread_sigmask()')
965 def test_pthread_sigmask_arguments(self):
966 self.assertRaises(TypeError, signal.pthread_sigmask)
967 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
968 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
969 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
Antoine Pitrou9d3627e2018-05-04 13:00:50 +0200970 with self.assertRaises(ValueError):
971 signal.pthread_sigmask(signal.SIG_BLOCK, [signal.NSIG])
Serhiy Storchakad54cfb12018-05-08 07:48:50 +0300972 with self.assertRaises(ValueError):
973 signal.pthread_sigmask(signal.SIG_BLOCK, [0])
974 with self.assertRaises(ValueError):
975 signal.pthread_sigmask(signal.SIG_BLOCK, [1<<1000])
Antoine Pitrou9d3627e2018-05-04 13:00:50 +0200976
977 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
978 'need signal.pthread_sigmask()')
979 def test_pthread_sigmask_valid_signals(self):
980 s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals())
981 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, s)
982 # Get current blocked set
983 s = signal.pthread_sigmask(signal.SIG_UNBLOCK, signal.valid_signals())
984 self.assertLessEqual(s, signal.valid_signals())
Victor Stinnerb3e72192011-05-08 01:46:11 +0200985
986 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
987 'need signal.pthread_sigmask()')
988 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200989 code = """if 1:
990 import signal
991 import os; import threading
992
993 def handler(signum, frame):
994 1/0
995
996 def kill(signum):
997 os.kill(os.getpid(), signum)
998
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200999 def check_mask(mask):
1000 for sig in mask:
1001 assert isinstance(sig, signal.Signals), repr(sig)
1002
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001003 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001004 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
1005 check_mask(sigmask)
1006 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001007
Victor Stinnerb3e72192011-05-08 01:46:11 +02001008 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +02001009
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001010 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001011 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +02001012
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001013 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +02001014 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001015 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001016 try:
1017 kill(signum)
1018 except ZeroDivisionError:
1019 pass
1020 else:
1021 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001022
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001023 # Block and then raise SIGUSR1. The signal is blocked: the signal
1024 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001025 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
1026 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001027 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +02001028
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001029 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001030 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001031 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +02001032 if signum not in blocked:
1033 raise Exception("%s not in %s" % (signum, blocked))
1034 if old_mask ^ blocked != {signum}:
1035 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +02001036
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001037 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001038 try:
R David Murrayfc069992013-12-13 20:52:19 -05001039 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001040 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001041 except ZeroDivisionError:
1042 pass
1043 else:
1044 raise Exception("ZeroDivisionError not raised")
1045 try:
1046 kill(signum)
1047 except ZeroDivisionError:
1048 pass
1049 else:
1050 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001051
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001052 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001053 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +02001054 if signum in unblocked:
1055 raise Exception("%s in %s" % (signum, unblocked))
1056 if blocked ^ unblocked != {signum}:
1057 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
1058 if old_mask != unblocked:
1059 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001060 """
1061 assert_python_ok('-c', code)
1062
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001063 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
1064 'need signal.pthread_kill()')
1065 def test_pthread_kill_main_thread(self):
1066 # Test that a signal can be sent to the main thread with pthread_kill()
1067 # before any other thread has been created (see issue #12392).
1068 code = """if True:
1069 import threading
1070 import signal
1071 import sys
1072
1073 def handler(signum, frame):
1074 sys.exit(3)
1075
1076 signal.signal(signal.SIGUSR1, handler)
1077 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1078 sys.exit(2)
1079 """
1080
1081 with spawn_python('-c', code) as process:
1082 stdout, stderr = process.communicate()
1083 exitcode = process.wait()
1084 if exitcode != 3:
1085 raise Exception("Child error (exit code %s): %s" %
1086 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001087
1088
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001089class StressTest(unittest.TestCase):
1090 """
1091 Stress signal delivery, especially when a signal arrives in
1092 the middle of recomputing the signal state or executing
1093 previously tripped signal handlers.
1094 """
1095
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001096 def setsig(self, signum, handler):
1097 old_handler = signal.signal(signum, handler)
1098 self.addCleanup(signal.signal, signum, old_handler)
1099
1100 def measure_itimer_resolution(self):
1101 N = 20
1102 times = []
1103
1104 def handler(signum=None, frame=None):
1105 if len(times) < N:
1106 times.append(time.perf_counter())
1107 # 1 µs is the smallest possible timer interval,
1108 # we want to measure what the concrete duration
1109 # will be on this platform
1110 signal.setitimer(signal.ITIMER_REAL, 1e-6)
1111
1112 self.addCleanup(signal.setitimer, signal.ITIMER_REAL, 0)
1113 self.setsig(signal.SIGALRM, handler)
1114 handler()
1115 while len(times) < N:
1116 time.sleep(1e-3)
1117
1118 durations = [times[i+1] - times[i] for i in range(len(times) - 1)]
1119 med = statistics.median(durations)
1120 if support.verbose:
1121 print("detected median itimer() resolution: %.6f s." % (med,))
1122 return med
1123
1124 def decide_itimer_count(self):
1125 # Some systems have poor setitimer() resolution (for example
1126 # measured around 20 ms. on FreeBSD 9), so decide on a reasonable
1127 # number of sequential timers based on that.
1128 reso = self.measure_itimer_resolution()
1129 if reso <= 1e-4:
1130 return 10000
1131 elif reso <= 1e-2:
1132 return 100
1133 else:
1134 self.skipTest("detected itimer resolution (%.3f s.) too high "
1135 "(> 10 ms.) on this platform (or system too busy)"
1136 % (reso,))
1137
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001138 @unittest.skipUnless(hasattr(signal, "setitimer"),
1139 "test needs setitimer()")
1140 def test_stress_delivery_dependent(self):
1141 """
1142 This test uses dependent signal handlers.
1143 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001144 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001145 sigs = []
1146
1147 def first_handler(signum, frame):
1148 # 1e-6 is the minimum non-zero value for `setitimer()`.
1149 # Choose a random delay so as to improve chances of
1150 # triggering a race condition. Ideally the signal is received
1151 # when inside critical signal-handling routines such as
1152 # Py_MakePendingCalls().
1153 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1154
1155 def second_handler(signum=None, frame=None):
1156 sigs.append(signum)
1157
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001158 # Here on Linux, SIGPROF > SIGALRM > SIGUSR1. By using both
1159 # ascending and descending sequences (SIGUSR1 then SIGALRM,
1160 # SIGPROF then SIGALRM), we maximize chances of hitting a bug.
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001161 self.setsig(signal.SIGPROF, first_handler)
1162 self.setsig(signal.SIGUSR1, first_handler)
1163 self.setsig(signal.SIGALRM, second_handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001164
1165 expected_sigs = 0
Victor Stinner2cf4c202018-12-17 09:36:36 +01001166 deadline = time.monotonic() + 15.0
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001167
1168 while expected_sigs < N:
1169 os.kill(os.getpid(), signal.SIGPROF)
1170 expected_sigs += 1
1171 # Wait for handlers to run to avoid signal coalescing
Victor Stinner2cf4c202018-12-17 09:36:36 +01001172 while len(sigs) < expected_sigs and time.monotonic() < deadline:
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001173 time.sleep(1e-5)
1174
1175 os.kill(os.getpid(), signal.SIGUSR1)
1176 expected_sigs += 1
Victor Stinner2cf4c202018-12-17 09:36:36 +01001177 while len(sigs) < expected_sigs and time.monotonic() < deadline:
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001178 time.sleep(1e-5)
1179
1180 # All ITIMER_REAL signals should have been delivered to the
1181 # Python handler
1182 self.assertEqual(len(sigs), N, "Some signals were lost")
1183
1184 @unittest.skipUnless(hasattr(signal, "setitimer"),
1185 "test needs setitimer()")
1186 def test_stress_delivery_simultaneous(self):
1187 """
1188 This test uses simultaneous signal handlers.
1189 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001190 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001191 sigs = []
1192
1193 def handler(signum, frame):
1194 sigs.append(signum)
1195
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001196 self.setsig(signal.SIGUSR1, handler)
1197 self.setsig(signal.SIGALRM, handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001198
1199 expected_sigs = 0
Victor Stinner2cf4c202018-12-17 09:36:36 +01001200 deadline = time.monotonic() + 15.0
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001201
1202 while expected_sigs < N:
1203 # Hopefully the SIGALRM will be received somewhere during
1204 # initial processing of SIGUSR1.
1205 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1206 os.kill(os.getpid(), signal.SIGUSR1)
1207
1208 expected_sigs += 2
1209 # Wait for handlers to run to avoid signal coalescing
Victor Stinner2cf4c202018-12-17 09:36:36 +01001210 while len(sigs) < expected_sigs and time.monotonic() < deadline:
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001211 time.sleep(1e-5)
1212
1213 # All ITIMER_REAL signals should have been delivered to the
1214 # Python handler
1215 self.assertEqual(len(sigs), N, "Some signals were lost")
1216
Vladimir Matveevc24c6c22019-01-08 01:58:25 -08001217class RaiseSignalTest(unittest.TestCase):
1218
1219 def test_sigint(self):
1220 try:
1221 signal.raise_signal(signal.SIGINT)
1222 self.fail("Expected KeyInterrupt")
1223 except KeyboardInterrupt:
1224 pass
1225
1226 @unittest.skipIf(sys.platform != "win32", "Windows specific test")
1227 def test_invalid_argument(self):
1228 try:
1229 SIGHUP = 1 # not supported on win32
1230 signal.raise_signal(SIGHUP)
1231 self.fail("OSError (Invalid argument) expected")
1232 except OSError as e:
1233 if e.errno == errno.EINVAL:
1234 pass
1235 else:
1236 raise
1237
1238 def test_handler(self):
1239 is_ok = False
1240 def handler(a, b):
1241 nonlocal is_ok
1242 is_ok = True
1243 old_signal = signal.signal(signal.SIGINT, handler)
1244 self.addCleanup(signal.signal, signal.SIGINT, old_signal)
1245
1246 signal.raise_signal(signal.SIGINT)
1247 self.assertTrue(is_ok)
1248
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001249
Zachary Ware38c707e2015-04-13 15:00:43 -05001250def tearDownModule():
1251 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001252
1253if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001254 unittest.main()