blob: 354c3fde168c32e265f8c86e4d8696bb00515751 [file] [log] [blame]
Victor Stinnerd6debb22017-03-27 16:05:26 +02001import os
Antoine Pitrouc08177a2017-06-28 23:29:29 +02002import random
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00003import signal
Victor Stinner11517102014-07-29 23:31:34 +02004import socket
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02005import statistics
Christian Heimes4fbc72b2008-03-22 00:47:35 +00006import subprocess
Victor Stinnerd6debb22017-03-27 16:05:26 +02007import sys
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02008import threading
Victor Stinnerd6debb22017-03-27 16:05:26 +02009import time
10import unittest
11from test import support
Berker Peksagce643912015-05-06 06:33:17 +030012from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020013try:
Victor Stinner56e8c292014-07-21 12:30:22 +020014 import _testcapi
15except ImportError:
16 _testcapi = None
Christian Heimesc06950e2008-02-28 21:17:00 +000017
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000018
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020019class GenericTests(unittest.TestCase):
20
21 def test_enums(self):
22 for name in dir(signal):
23 sig = getattr(signal, name)
24 if name in {'SIG_DFL', 'SIG_IGN'}:
25 self.assertIsInstance(sig, signal.Handlers)
26 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
27 self.assertIsInstance(sig, signal.Sigmasks)
28 elif name.startswith('SIG') and not name.startswith('SIG_'):
29 self.assertIsInstance(sig, signal.Signals)
30 elif name.startswith('CTRL_'):
31 self.assertIsInstance(sig, signal.Signals)
32 self.assertEqual(sys.platform, "win32")
33
34
Brian Curtin3f004b12010-08-06 19:34:52 +000035@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +020036class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +000037 def trivial_signal_handler(self, *args):
38 pass
39
Thomas Woutersed03b412007-08-28 21:37:11 +000040 def test_out_of_range_signal_number_raises_error(self):
41 self.assertRaises(ValueError, signal.getsignal, 4242)
42
Thomas Woutersed03b412007-08-28 21:37:11 +000043 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +000044 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +000045
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010046 self.assertRaises(ValueError, signal.strsignal, 4242)
47
Thomas Woutersed03b412007-08-28 21:37:11 +000048 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
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010060 def test_strsignal(self):
Antoine Pietri019f5b32018-03-12 20:03:14 +010061 self.assertIn("Interrupt", signal.strsignal(signal.SIGINT))
62 self.assertIn("Terminated", signal.strsignal(signal.SIGTERM))
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010063
Victor Stinner32eb8402016-03-15 11:12:35 +010064 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner32eb8402016-03-15 11:12:35 +010065 def test_interprocess_signal(self):
66 dirname = os.path.dirname(__file__)
67 script = os.path.join(dirname, 'signalinterproctester.py')
68 assert_python_ok(script)
69
Antoine Pitrou9d3627e2018-05-04 13:00:50 +020070 def test_valid_signals(self):
71 s = signal.valid_signals()
72 self.assertIsInstance(s, set)
73 self.assertIn(signal.Signals.SIGINT, s)
74 self.assertIn(signal.Signals.SIGALRM, s)
75 self.assertNotIn(0, s)
76 self.assertNotIn(signal.NSIG, s)
77 self.assertLess(len(s), signal.NSIG)
78
Christian Heimes4fbc72b2008-03-22 00:47:35 +000079
Brian Curtin3f004b12010-08-06 19:34:52 +000080@unittest.skipUnless(sys.platform == "win32", "Windows specific")
81class WindowsSignalTests(unittest.TestCase):
Antoine Pitrou9d3627e2018-05-04 13:00:50 +020082
83 def test_valid_signals(self):
84 s = signal.valid_signals()
85 self.assertIsInstance(s, set)
86 self.assertGreaterEqual(len(s), 6)
87 self.assertIn(signal.Signals.SIGINT, s)
88 self.assertNotIn(0, s)
89 self.assertNotIn(signal.NSIG, s)
90 self.assertLess(len(s), signal.NSIG)
91
Brian Curtin3f004b12010-08-06 19:34:52 +000092 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +000093 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +000094 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +100095 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +000096 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
97 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
98 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +100099 # Set and then reset a handler for signals that work on windows.
100 # Issue #18396, only for signals without a C-level handler.
101 if signal.getsignal(sig) is not None:
102 signal.signal(sig, signal.signal(sig, handler))
103 checked.add(sig)
104 # Issue #18396: Ensure the above loop at least tested *something*
105 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +0000106
107 with self.assertRaises(ValueError):
108 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000109
110 with self.assertRaises(ValueError):
111 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000112
113
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500114class WakeupFDTests(unittest.TestCase):
115
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800116 def test_invalid_call(self):
117 # First parameter is positional-only
118 with self.assertRaises(TypeError):
119 signal.set_wakeup_fd(signum=signal.SIGINT)
120
121 # warn_on_full_buffer is a keyword-only parameter
122 with self.assertRaises(TypeError):
123 signal.set_wakeup_fd(signal.SIGINT, False)
124
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500125 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200126 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +0200127 self.assertRaises((ValueError, OSError),
128 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500129
Victor Stinner11517102014-07-29 23:31:34 +0200130 def test_invalid_socket(self):
131 sock = socket.socket()
132 fd = sock.fileno()
133 sock.close()
134 self.assertRaises((ValueError, OSError),
135 signal.set_wakeup_fd, fd)
136
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200137 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200138 r1, w1 = os.pipe()
139 self.addCleanup(os.close, r1)
140 self.addCleanup(os.close, w1)
141 r2, w2 = os.pipe()
142 self.addCleanup(os.close, r2)
143 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200144
Victor Stinner7cea44d2014-08-27 14:02:36 +0200145 if hasattr(os, 'set_blocking'):
146 os.set_blocking(w1, False)
147 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200148
Victor Stinner1d8948e2014-07-24 22:51:05 +0200149 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200150 self.assertEqual(signal.set_wakeup_fd(w2), w1)
151 self.assertEqual(signal.set_wakeup_fd(-1), w2)
152 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200153
Victor Stinner11517102014-07-29 23:31:34 +0200154 def test_set_wakeup_fd_socket_result(self):
155 sock1 = socket.socket()
156 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200157 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200158 fd1 = sock1.fileno()
159
160 sock2 = socket.socket()
161 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200162 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200163 fd2 = sock2.fileno()
164
165 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200166 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
167 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
168 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200169
Victor Stinner38227602014-08-27 12:59:44 +0200170 # On Windows, files are always blocking and Windows does not provide a
171 # function to test if a socket is in non-blocking mode.
172 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
173 def test_set_wakeup_fd_blocking(self):
174 rfd, wfd = os.pipe()
175 self.addCleanup(os.close, rfd)
176 self.addCleanup(os.close, wfd)
177
178 # fd must be non-blocking
179 os.set_blocking(wfd, True)
180 with self.assertRaises(ValueError) as cm:
181 signal.set_wakeup_fd(wfd)
182 self.assertEqual(str(cm.exception),
183 "the fd %s must be in non-blocking mode" % wfd)
184
185 # non-blocking is ok
186 os.set_blocking(wfd, False)
187 signal.set_wakeup_fd(wfd)
188 signal.set_wakeup_fd(-1)
189
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500190
Brian Curtin3f004b12010-08-06 19:34:52 +0000191@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000192class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200193 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200194 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200195 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200196 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200197 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200198 import os
199 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200200 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000201
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200202 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200203
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200204 def handler(signum, frame):
205 pass
206
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200207 def check_signum(signals):
208 data = os.read(read, len(signals)+1)
209 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200210 if not {!r}:
211 raised = set(raised)
212 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200213 if raised != signals:
214 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200215
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200216 {}
217
218 signal.signal(signal.SIGALRM, handler)
219 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200220 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200221 signal.set_wakeup_fd(write)
222
223 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200224 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200225
226 os.close(read)
227 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200228 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200229
230 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200231
Victor Stinner56e8c292014-07-21 12:30:22 +0200232 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200233 def test_wakeup_write_error(self):
234 # Issue #16105: write() errors in the C signal handler should not
235 # pass silently.
236 # Use a subprocess to have only one thread.
237 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200238 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200239 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200240 import os
241 import signal
242 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200243 from test.support import captured_stderr
244
245 def handler(signum, frame):
246 1/0
247
248 signal.signal(signal.SIGALRM, handler)
249 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200250 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200251
252 # Set wakeup_fd a read-only file descriptor to trigger the error
253 signal.set_wakeup_fd(r)
254 try:
255 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200256 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200257 except ZeroDivisionError:
258 # An ignored exception should have been printed out on stderr
259 err = err.getvalue()
260 if ('Exception ignored when trying to write to the signal wakeup fd'
261 not in err):
262 raise AssertionError(err)
263 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
264 raise AssertionError(err)
265 else:
266 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200267
268 os.close(r)
269 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200270 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200271 r, w = os.pipe()
272 try:
273 os.write(r, b'x')
274 except OSError:
275 pass
276 else:
277 self.skipTest("OS doesn't report write() error on the read end of a pipe")
278 finally:
279 os.close(r)
280 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200281
282 assert_python_ok('-c', code)
283
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000284 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200285 self.check_wakeup("""def test():
286 import select
287 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000288
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200289 TIMEOUT_FULL = 10
290 TIMEOUT_HALF = 5
291
Victor Stinner749a6a82015-03-30 22:09:14 +0200292 class InterruptSelect(Exception):
293 pass
294
295 def handler(signum, frame):
296 raise InterruptSelect
297 signal.signal(signal.SIGALRM, handler)
298
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200299 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100300
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200301 # We attempt to get a signal during the sleep,
302 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100303 try:
304 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200305 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100306 pass
307 else:
308 raise Exception("select() was not interrupted")
309
310 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200311 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100312 after_time = time.monotonic()
313 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200314 if dt >= TIMEOUT_HALF:
315 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200316 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000317
318 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200319 self.check_wakeup("""def test():
320 import select
321 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000322
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200323 TIMEOUT_FULL = 10
324 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000325
Victor Stinner749a6a82015-03-30 22:09:14 +0200326 class InterruptSelect(Exception):
327 pass
328
329 def handler(signum, frame):
330 raise InterruptSelect
331 signal.signal(signal.SIGALRM, handler)
332
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200333 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100334 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200335 # We attempt to get a signal during the select call
336 try:
337 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200338 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200339 pass
340 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200341 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100342 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200343 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200344 if dt >= TIMEOUT_HALF:
345 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200346 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200347
348 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200349 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200350 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200351 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200352 _testcapi.raise_signal(signal.SIGUSR1)
353 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200354 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000355
Victor Stinnerc13ef662011-05-25 02:35:58 +0200356 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
357 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200358 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200359 self.check_wakeup("""def test():
360 signum1 = signal.SIGUSR1
361 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200362
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200363 signal.signal(signum1, handler)
364 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200365
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200366 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200367 _testcapi.raise_signal(signum1)
368 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200369 # Unblocking the 2 signals calls the C signal handler twice
370 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200371 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200372
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000373
Victor Stinner11517102014-07-29 23:31:34 +0200374@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
375class WakeupSocketSignalTests(unittest.TestCase):
376
377 @unittest.skipIf(_testcapi is None, 'need _testcapi')
378 def test_socket(self):
379 # use a subprocess to have only one thread
380 code = """if 1:
381 import signal
382 import socket
383 import struct
384 import _testcapi
385
386 signum = signal.SIGINT
387 signals = (signum,)
388
389 def handler(signum, frame):
390 pass
391
392 signal.signal(signum, handler)
393
394 read, write = socket.socketpair()
395 read.setblocking(False)
396 write.setblocking(False)
397 signal.set_wakeup_fd(write.fileno())
398
399 _testcapi.raise_signal(signum)
400
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:
448 _testcapi.raise_signal(signum)
449
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()
483 read.setblocking(False)
484 write.setblocking(False)
485
486 # Fill the send buffer
487 try:
488 while True:
489 write.send(b"x")
490 except BlockingIOError:
491 pass
492
493 # By default, we get a warning when a signal arrives
494 signal.set_wakeup_fd(write.fileno())
495
496 with captured_stderr() as err:
497 _testcapi.raise_signal(signum)
498
499 err = err.getvalue()
500 if ('Exception ignored when trying to {action} to the signal wakeup fd'
501 not in err):
502 raise AssertionError(err)
503
504 # And also if warn_on_full_buffer=True
505 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=True)
506
507 with captured_stderr() as err:
508 _testcapi.raise_signal(signum)
509
510 err = err.getvalue()
511 if ('Exception ignored when trying to {action} to the signal wakeup fd'
512 not in err):
513 raise AssertionError(err)
514
515 # But not if warn_on_full_buffer=False
516 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=False)
517
518 with captured_stderr() as err:
519 _testcapi.raise_signal(signum)
520
521 err = err.getvalue()
522 if err != "":
523 raise AssertionError("got unexpected output %r" % (err,))
524
525 # And then check the default again, to make sure warn_on_full_buffer
526 # settings don't leak across calls.
527 signal.set_wakeup_fd(write.fileno())
528
529 with captured_stderr() as err:
530 _testcapi.raise_signal(signum)
531
532 err = err.getvalue()
533 if ('Exception ignored when trying to {action} to the signal wakeup fd'
534 not in err):
535 raise AssertionError(err)
536
537 """.format(action=action)
538 assert_python_ok('-c', code)
539
Victor Stinner11517102014-07-29 23:31:34 +0200540
Brian Curtin3f004b12010-08-06 19:34:52 +0000541@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000542class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000543
Victor Stinnerd6284962011-06-20 23:28:09 +0200544 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000545 """Perform a read during which a signal will arrive. Return True if the
546 read is interrupted by the signal and raises an exception. Return False
547 if it returns normally.
548 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200549 # use a subprocess to have only one thread, to have a timeout on the
550 # blocking read and to not touch signal handling in this process
551 code = """if 1:
552 import errno
553 import os
554 import signal
555 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000556
Victor Stinnerd6284962011-06-20 23:28:09 +0200557 interrupt = %r
558 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000559
Victor Stinnerd6284962011-06-20 23:28:09 +0200560 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000561 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200562
563 signal.signal(signal.SIGALRM, handler)
564 if interrupt is not None:
565 signal.siginterrupt(signal.SIGALRM, interrupt)
566
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200567 print("ready")
568 sys.stdout.flush()
569
Victor Stinnerd6284962011-06-20 23:28:09 +0200570 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200571 try:
572 for loop in range(2):
573 # send a SIGALRM in a second (during the read)
574 signal.alarm(1)
575 try:
576 # blocking call: read from a pipe without data
577 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000578 except ZeroDivisionError:
579 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200580 else:
581 sys.exit(2)
582 sys.exit(3)
583 finally:
584 os.close(r)
585 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200586 """ % (interrupt,)
587 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000588 try:
Victor Stinner45273652011-06-22 22:15:51 +0200589 # wait until the child process is loaded and has started
590 first_line = process.stdout.readline()
591
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200592 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200593 except subprocess.TimeoutExpired:
594 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000595 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200596 else:
Victor Stinner45273652011-06-22 22:15:51 +0200597 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200598 exitcode = process.wait()
599 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200600 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200601 % (exitcode, stdout))
602 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000603
604 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200605 # If a signal handler is installed and siginterrupt is not called
606 # at all, when that signal arrives, it interrupts a syscall that's in
607 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200608 interrupted = self.readpipe_interrupted(None)
609 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000610
611 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200612 # If a signal handler is installed and siginterrupt is called with
613 # a true value for the second argument, when that signal arrives, it
614 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200615 interrupted = self.readpipe_interrupted(True)
616 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000617
618 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200619 # If a signal handler is installed and siginterrupt is called with
620 # a false value for the second argument, when that signal arrives, it
621 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200622 interrupted = self.readpipe_interrupted(False)
623 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000624
625
Brian Curtin3f004b12010-08-06 19:34:52 +0000626@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000627class ItimerTest(unittest.TestCase):
628 def setUp(self):
629 self.hndl_called = False
630 self.hndl_count = 0
631 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000632 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000633
634 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000635 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000636 if self.itimer is not None: # test_itimer_exc doesn't change this attr
637 # just ensure that itimer is stopped
638 signal.setitimer(self.itimer, 0)
639
640 def sig_alrm(self, *args):
641 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000642
643 def sig_vtalrm(self, *args):
644 self.hndl_called = True
645
646 if self.hndl_count > 3:
647 # it shouldn't be here, because it should have been disabled.
648 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
649 "timer.")
650 elif self.hndl_count == 3:
651 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
652 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000653
654 self.hndl_count += 1
655
Martin v. Löwis823725e2008-03-24 13:39:54 +0000656 def sig_prof(self, *args):
657 self.hndl_called = True
658 signal.setitimer(signal.ITIMER_PROF, 0)
659
Martin v. Löwis823725e2008-03-24 13:39:54 +0000660 def test_itimer_exc(self):
661 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
662 # defines it ?
663 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000664 # Negative times are treated as zero on some platforms.
665 if 0:
666 self.assertRaises(signal.ItimerError,
667 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000668
669 def test_itimer_real(self):
670 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000671 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000672 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000673 self.assertEqual(self.hndl_called, True)
674
R. David Murray44546f82010-04-21 01:59:28 +0000675 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner13ff2452018-01-22 18:32:50 +0100676 @unittest.skipIf(sys.platform in ('netbsd5',),
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000677 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000678 def test_itimer_virtual(self):
679 self.itimer = signal.ITIMER_VIRTUAL
680 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
681 signal.setitimer(self.itimer, 0.3, 0.2)
682
Victor Stinner79d68f92015-03-19 21:54:09 +0100683 start_time = time.monotonic()
684 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000685 # use up some virtual time by doing real work
686 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000687 if signal.getitimer(self.itimer) == (0.0, 0.0):
688 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000689 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000690 self.skipTest("timeout: likely cause: machine too slow or load too "
691 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000692
693 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000694 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000695 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000696 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000697
698 def test_itimer_prof(self):
699 self.itimer = signal.ITIMER_PROF
700 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000701 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000702
Victor Stinner79d68f92015-03-19 21:54:09 +0100703 start_time = time.monotonic()
704 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000705 # do some work
706 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000707 if signal.getitimer(self.itimer) == (0.0, 0.0):
708 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000709 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000710 self.skipTest("timeout: likely cause: machine too slow or load too "
711 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000712
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000713 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000714 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000715 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000716 self.assertEqual(self.hndl_called, True)
717
Antoine Pitrou729780a2017-06-30 10:01:05 +0200718 def test_setitimer_tiny(self):
719 # bpo-30807: C setitimer() takes a microsecond-resolution interval.
720 # Check that float -> timeval conversion doesn't round
721 # the interval down to zero, which would disable the timer.
722 self.itimer = signal.ITIMER_REAL
723 signal.setitimer(self.itimer, 1e-6)
724 time.sleep(1)
725 self.assertEqual(self.hndl_called, True)
726
Victor Stinnera9293352011-04-30 15:21:58 +0200727
Victor Stinner35b300c2011-05-04 13:20:35 +0200728class PendingSignalsTests(unittest.TestCase):
729 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200730 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
731 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200732 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200733 @unittest.skipUnless(hasattr(signal, 'sigpending'),
734 'need signal.sigpending()')
735 def test_sigpending_empty(self):
736 self.assertEqual(signal.sigpending(), set())
737
738 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
739 'need signal.pthread_sigmask()')
740 @unittest.skipUnless(hasattr(signal, 'sigpending'),
741 'need signal.sigpending()')
742 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200743 code = """if 1:
744 import os
745 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200746
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200747 def handler(signum, frame):
748 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200749
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200750 signum = signal.SIGUSR1
751 signal.signal(signum, handler)
752
753 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
754 os.kill(os.getpid(), signum)
755 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200756 for sig in pending:
757 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200758 if pending != {signum}:
759 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200760 try:
761 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
762 except ZeroDivisionError:
763 pass
764 else:
765 raise Exception("ZeroDivisionError not raised")
766 """
767 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200768
769 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
770 'need signal.pthread_kill()')
771 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200772 code = """if 1:
773 import signal
774 import threading
775 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200776
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200777 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200778
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200779 def handler(signum, frame):
780 1/0
781
782 signal.signal(signum, handler)
783
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200784 tid = threading.get_ident()
785 try:
786 signal.pthread_kill(tid, signum)
787 except ZeroDivisionError:
788 pass
789 else:
790 raise Exception("ZeroDivisionError not raised")
791 """
792 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200793
Victor Stinner7f294d12011-06-10 14:02:10 +0200794 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
795 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200796 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200797 """
798 test: body of the "def test(signum):" function.
799 blocked: number of the blocked signal
800 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200801 code = '''if 1:
802 import signal
803 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200804 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200805
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200806 def handler(signum, frame):
807 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200808
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200809 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200810
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200811 blocked = %s
812 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200813
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200814 # child: block and wait the signal
815 try:
816 signal.signal(signum, handler)
817 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200818
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200819 # Do the tests
820 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200821
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200822 # The handler must not be called on unblock
823 try:
824 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
825 except ZeroDivisionError:
826 print("the signal handler has been called",
827 file=sys.stderr)
828 sys.exit(1)
829 except BaseException as err:
830 print("error: {}".format(err), file=sys.stderr)
831 sys.stderr.flush()
832 sys.exit(1)
833 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200834
Ross Lagerwallbc808222011-06-25 12:13:40 +0200835 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200836 # process might have several threads running, use a subprocess to have
837 # a single thread.
838 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200839
Victor Stinnerb3e72192011-05-08 01:46:11 +0200840 @unittest.skipUnless(hasattr(signal, 'sigwait'),
841 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200842 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200843 self.wait_helper(signal.SIGALRM, '''
844 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200845 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200846 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200847 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200848 if received != signum:
849 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200850 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200851
852 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
853 'need signal.sigwaitinfo()')
854 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200855 self.wait_helper(signal.SIGALRM, '''
856 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200857 signal.alarm(1)
858 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200859 if info.si_signo != signum:
860 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200861 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200862
863 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
864 'need signal.sigtimedwait()')
865 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200866 self.wait_helper(signal.SIGALRM, '''
867 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200868 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100869 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200870 if info.si_signo != signum:
871 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200872 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200873
Ross Lagerwallbc808222011-06-25 12:13:40 +0200874 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
875 'need signal.sigtimedwait()')
876 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200877 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200878 self.wait_helper(signal.SIGALRM, '''
879 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200880 import os
881 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100882 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200883 if info.si_signo != signum:
884 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200885 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200886
887 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
888 'need signal.sigtimedwait()')
889 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200890 self.wait_helper(signal.SIGALRM, '''
891 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100892 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200893 if received is not None:
894 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200895 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200896
897 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
898 'need signal.sigtimedwait()')
899 def test_sigtimedwait_negative_timeout(self):
900 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100901 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200902
Ross Lagerwallbc808222011-06-25 12:13:40 +0200903 @unittest.skipUnless(hasattr(signal, 'sigwait'),
904 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200905 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
906 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200907 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200908 # Check that calling sigwait() from a thread doesn't suspend the whole
909 # process. A new interpreter is spawned to avoid problems when mixing
910 # threads and fork(): only async-safe functions are allowed between
911 # fork() and exec().
912 assert_python_ok("-c", """if True:
913 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200914
Victor Stinner415007e2011-06-13 16:19:06 +0200915 # the default handler terminates the process
916 signum = signal.SIGUSR1
917
918 def kill_later():
919 # wait until the main thread is waiting in sigwait()
920 time.sleep(1)
921 os.kill(os.getpid(), signum)
922
923 # the signal must be blocked by all the threads
924 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
925 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200926 killer.start()
927 received = signal.sigwait([signum])
928 if received != signum:
929 print("sigwait() received %s, not %s" % (received, signum),
930 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200931 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200932 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200933 # unblock the signal, which should have been cleared by sigwait()
934 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
935 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200936
Victor Stinnerb3e72192011-05-08 01:46:11 +0200937 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
938 'need signal.pthread_sigmask()')
939 def test_pthread_sigmask_arguments(self):
940 self.assertRaises(TypeError, signal.pthread_sigmask)
941 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
942 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
943 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
Antoine Pitrou9d3627e2018-05-04 13:00:50 +0200944 with self.assertRaises(ValueError):
945 signal.pthread_sigmask(signal.SIG_BLOCK, [signal.NSIG])
Serhiy Storchakad54cfb12018-05-08 07:48:50 +0300946 with self.assertRaises(ValueError):
947 signal.pthread_sigmask(signal.SIG_BLOCK, [0])
948 with self.assertRaises(ValueError):
949 signal.pthread_sigmask(signal.SIG_BLOCK, [1<<1000])
Antoine Pitrou9d3627e2018-05-04 13:00:50 +0200950
951 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
952 'need signal.pthread_sigmask()')
953 def test_pthread_sigmask_valid_signals(self):
954 s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals())
955 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, s)
956 # Get current blocked set
957 s = signal.pthread_sigmask(signal.SIG_UNBLOCK, signal.valid_signals())
958 self.assertLessEqual(s, signal.valid_signals())
Victor Stinnerb3e72192011-05-08 01:46:11 +0200959
960 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
961 'need signal.pthread_sigmask()')
962 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200963 code = """if 1:
964 import signal
965 import os; import threading
966
967 def handler(signum, frame):
968 1/0
969
970 def kill(signum):
971 os.kill(os.getpid(), signum)
972
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200973 def check_mask(mask):
974 for sig in mask:
975 assert isinstance(sig, signal.Signals), repr(sig)
976
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200977 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200978 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
979 check_mask(sigmask)
980 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200981
Victor Stinnerb3e72192011-05-08 01:46:11 +0200982 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200983
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200984 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200985 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200986
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200987 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200988 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200989 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200990 try:
991 kill(signum)
992 except ZeroDivisionError:
993 pass
994 else:
995 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200996
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200997 # Block and then raise SIGUSR1. The signal is blocked: the signal
998 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200999 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
1000 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001001 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +02001002
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001003 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001004 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001005 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +02001006 if signum not in blocked:
1007 raise Exception("%s not in %s" % (signum, blocked))
1008 if old_mask ^ blocked != {signum}:
1009 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +02001010
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001011 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001012 try:
R David Murrayfc069992013-12-13 20:52:19 -05001013 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001014 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001015 except ZeroDivisionError:
1016 pass
1017 else:
1018 raise Exception("ZeroDivisionError not raised")
1019 try:
1020 kill(signum)
1021 except ZeroDivisionError:
1022 pass
1023 else:
1024 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001025
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001026 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001027 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +02001028 if signum in unblocked:
1029 raise Exception("%s in %s" % (signum, unblocked))
1030 if blocked ^ unblocked != {signum}:
1031 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
1032 if old_mask != unblocked:
1033 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001034 """
1035 assert_python_ok('-c', code)
1036
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001037 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
1038 'need signal.pthread_kill()')
1039 def test_pthread_kill_main_thread(self):
1040 # Test that a signal can be sent to the main thread with pthread_kill()
1041 # before any other thread has been created (see issue #12392).
1042 code = """if True:
1043 import threading
1044 import signal
1045 import sys
1046
1047 def handler(signum, frame):
1048 sys.exit(3)
1049
1050 signal.signal(signal.SIGUSR1, handler)
1051 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1052 sys.exit(2)
1053 """
1054
1055 with spawn_python('-c', code) as process:
1056 stdout, stderr = process.communicate()
1057 exitcode = process.wait()
1058 if exitcode != 3:
1059 raise Exception("Child error (exit code %s): %s" %
1060 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001061
1062
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001063class StressTest(unittest.TestCase):
1064 """
1065 Stress signal delivery, especially when a signal arrives in
1066 the middle of recomputing the signal state or executing
1067 previously tripped signal handlers.
1068 """
1069
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001070 def setsig(self, signum, handler):
1071 old_handler = signal.signal(signum, handler)
1072 self.addCleanup(signal.signal, signum, old_handler)
1073
1074 def measure_itimer_resolution(self):
1075 N = 20
1076 times = []
1077
1078 def handler(signum=None, frame=None):
1079 if len(times) < N:
1080 times.append(time.perf_counter())
1081 # 1 µs is the smallest possible timer interval,
1082 # we want to measure what the concrete duration
1083 # will be on this platform
1084 signal.setitimer(signal.ITIMER_REAL, 1e-6)
1085
1086 self.addCleanup(signal.setitimer, signal.ITIMER_REAL, 0)
1087 self.setsig(signal.SIGALRM, handler)
1088 handler()
1089 while len(times) < N:
1090 time.sleep(1e-3)
1091
1092 durations = [times[i+1] - times[i] for i in range(len(times) - 1)]
1093 med = statistics.median(durations)
1094 if support.verbose:
1095 print("detected median itimer() resolution: %.6f s." % (med,))
1096 return med
1097
1098 def decide_itimer_count(self):
1099 # Some systems have poor setitimer() resolution (for example
1100 # measured around 20 ms. on FreeBSD 9), so decide on a reasonable
1101 # number of sequential timers based on that.
1102 reso = self.measure_itimer_resolution()
1103 if reso <= 1e-4:
1104 return 10000
1105 elif reso <= 1e-2:
1106 return 100
1107 else:
1108 self.skipTest("detected itimer resolution (%.3f s.) too high "
1109 "(> 10 ms.) on this platform (or system too busy)"
1110 % (reso,))
1111
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001112 @unittest.skipUnless(hasattr(signal, "setitimer"),
1113 "test needs setitimer()")
1114 def test_stress_delivery_dependent(self):
1115 """
1116 This test uses dependent signal handlers.
1117 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001118 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001119 sigs = []
1120
1121 def first_handler(signum, frame):
1122 # 1e-6 is the minimum non-zero value for `setitimer()`.
1123 # Choose a random delay so as to improve chances of
1124 # triggering a race condition. Ideally the signal is received
1125 # when inside critical signal-handling routines such as
1126 # Py_MakePendingCalls().
1127 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1128
1129 def second_handler(signum=None, frame=None):
1130 sigs.append(signum)
1131
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001132 # Here on Linux, SIGPROF > SIGALRM > SIGUSR1. By using both
1133 # ascending and descending sequences (SIGUSR1 then SIGALRM,
1134 # SIGPROF then SIGALRM), we maximize chances of hitting a bug.
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001135 self.setsig(signal.SIGPROF, first_handler)
1136 self.setsig(signal.SIGUSR1, first_handler)
1137 self.setsig(signal.SIGALRM, second_handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001138
1139 expected_sigs = 0
1140 deadline = time.time() + 15.0
1141
1142 while expected_sigs < N:
1143 os.kill(os.getpid(), signal.SIGPROF)
1144 expected_sigs += 1
1145 # Wait for handlers to run to avoid signal coalescing
1146 while len(sigs) < expected_sigs and time.time() < deadline:
1147 time.sleep(1e-5)
1148
1149 os.kill(os.getpid(), signal.SIGUSR1)
1150 expected_sigs += 1
1151 while len(sigs) < expected_sigs and time.time() < deadline:
1152 time.sleep(1e-5)
1153
1154 # All ITIMER_REAL signals should have been delivered to the
1155 # Python handler
1156 self.assertEqual(len(sigs), N, "Some signals were lost")
1157
1158 @unittest.skipUnless(hasattr(signal, "setitimer"),
1159 "test needs setitimer()")
1160 def test_stress_delivery_simultaneous(self):
1161 """
1162 This test uses simultaneous signal handlers.
1163 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001164 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001165 sigs = []
1166
1167 def handler(signum, frame):
1168 sigs.append(signum)
1169
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001170 self.setsig(signal.SIGUSR1, handler)
1171 self.setsig(signal.SIGALRM, handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001172
1173 expected_sigs = 0
1174 deadline = time.time() + 15.0
1175
1176 while expected_sigs < N:
1177 # Hopefully the SIGALRM will be received somewhere during
1178 # initial processing of SIGUSR1.
1179 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1180 os.kill(os.getpid(), signal.SIGUSR1)
1181
1182 expected_sigs += 2
1183 # Wait for handlers to run to avoid signal coalescing
1184 while len(sigs) < expected_sigs and time.time() < deadline:
1185 time.sleep(1e-5)
1186
1187 # All ITIMER_REAL signals should have been delivered to the
1188 # Python handler
1189 self.assertEqual(len(sigs), N, "Some signals were lost")
1190
1191
Zachary Ware38c707e2015-04-13 15:00:43 -05001192def tearDownModule():
1193 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001194
1195if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001196 unittest.main()