blob: 48b7a392e50b34fa14ec413cfd14f1dad345a6db [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
46 def test_setting_signal_handler_to_none_raises_error(self):
47 self.assertRaises(TypeError, signal.signal,
48 signal.SIGUSR1, None)
49
Christian Heimes4fbc72b2008-03-22 00:47:35 +000050 def test_getsignal(self):
51 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020052 self.assertIsInstance(hup, signal.Handlers)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000053 self.assertEqual(signal.getsignal(signal.SIGHUP),
54 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000055 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000056 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000057
Victor Stinner32eb8402016-03-15 11:12:35 +010058 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner32eb8402016-03-15 11:12:35 +010059 def test_interprocess_signal(self):
60 dirname = os.path.dirname(__file__)
61 script = os.path.join(dirname, 'signalinterproctester.py')
62 assert_python_ok(script)
63
Christian Heimes4fbc72b2008-03-22 00:47:35 +000064
Brian Curtin3f004b12010-08-06 19:34:52 +000065@unittest.skipUnless(sys.platform == "win32", "Windows specific")
66class WindowsSignalTests(unittest.TestCase):
67 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +000068 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +000069 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +100070 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +000071 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
72 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
73 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +100074 # Set and then reset a handler for signals that work on windows.
75 # Issue #18396, only for signals without a C-level handler.
76 if signal.getsignal(sig) is not None:
77 signal.signal(sig, signal.signal(sig, handler))
78 checked.add(sig)
79 # Issue #18396: Ensure the above loop at least tested *something*
80 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +000081
82 with self.assertRaises(ValueError):
83 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +000084
85 with self.assertRaises(ValueError):
86 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +000087
88
Benjamin Petersonc68a4a02013-01-18 00:10:24 -050089class WakeupFDTests(unittest.TestCase):
90
Nathaniel J. Smith902ab802017-12-17 20:10:18 -080091 def test_invalid_call(self):
92 # First parameter is positional-only
93 with self.assertRaises(TypeError):
94 signal.set_wakeup_fd(signum=signal.SIGINT)
95
96 # warn_on_full_buffer is a keyword-only parameter
97 with self.assertRaises(TypeError):
98 signal.set_wakeup_fd(signal.SIGINT, False)
99
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500100 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200101 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +0200102 self.assertRaises((ValueError, OSError),
103 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500104
Victor Stinner11517102014-07-29 23:31:34 +0200105 def test_invalid_socket(self):
106 sock = socket.socket()
107 fd = sock.fileno()
108 sock.close()
109 self.assertRaises((ValueError, OSError),
110 signal.set_wakeup_fd, fd)
111
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200112 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200113 r1, w1 = os.pipe()
114 self.addCleanup(os.close, r1)
115 self.addCleanup(os.close, w1)
116 r2, w2 = os.pipe()
117 self.addCleanup(os.close, r2)
118 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200119
Victor Stinner7cea44d2014-08-27 14:02:36 +0200120 if hasattr(os, 'set_blocking'):
121 os.set_blocking(w1, False)
122 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200123
Victor Stinner1d8948e2014-07-24 22:51:05 +0200124 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200125 self.assertEqual(signal.set_wakeup_fd(w2), w1)
126 self.assertEqual(signal.set_wakeup_fd(-1), w2)
127 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200128
Victor Stinner11517102014-07-29 23:31:34 +0200129 def test_set_wakeup_fd_socket_result(self):
130 sock1 = socket.socket()
131 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200132 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200133 fd1 = sock1.fileno()
134
135 sock2 = socket.socket()
136 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200137 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200138 fd2 = sock2.fileno()
139
140 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200141 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
142 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
143 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200144
Victor Stinner38227602014-08-27 12:59:44 +0200145 # On Windows, files are always blocking and Windows does not provide a
146 # function to test if a socket is in non-blocking mode.
147 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
148 def test_set_wakeup_fd_blocking(self):
149 rfd, wfd = os.pipe()
150 self.addCleanup(os.close, rfd)
151 self.addCleanup(os.close, wfd)
152
153 # fd must be non-blocking
154 os.set_blocking(wfd, True)
155 with self.assertRaises(ValueError) as cm:
156 signal.set_wakeup_fd(wfd)
157 self.assertEqual(str(cm.exception),
158 "the fd %s must be in non-blocking mode" % wfd)
159
160 # non-blocking is ok
161 os.set_blocking(wfd, False)
162 signal.set_wakeup_fd(wfd)
163 signal.set_wakeup_fd(-1)
164
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500165
Brian Curtin3f004b12010-08-06 19:34:52 +0000166@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000167class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200168 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200169 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200170 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200171 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200172 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200173 import os
174 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200175 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000176
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200177 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200178
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200179 def handler(signum, frame):
180 pass
181
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200182 def check_signum(signals):
183 data = os.read(read, len(signals)+1)
184 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200185 if not {!r}:
186 raised = set(raised)
187 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200188 if raised != signals:
189 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200190
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200191 {}
192
193 signal.signal(signal.SIGALRM, handler)
194 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200195 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200196 signal.set_wakeup_fd(write)
197
198 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200199 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200200
201 os.close(read)
202 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200203 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200204
205 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200206
Victor Stinner56e8c292014-07-21 12:30:22 +0200207 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200208 def test_wakeup_write_error(self):
209 # Issue #16105: write() errors in the C signal handler should not
210 # pass silently.
211 # Use a subprocess to have only one thread.
212 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200213 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200214 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200215 import os
216 import signal
217 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200218 from test.support import captured_stderr
219
220 def handler(signum, frame):
221 1/0
222
223 signal.signal(signal.SIGALRM, handler)
224 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200225 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200226
227 # Set wakeup_fd a read-only file descriptor to trigger the error
228 signal.set_wakeup_fd(r)
229 try:
230 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200231 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200232 except ZeroDivisionError:
233 # An ignored exception should have been printed out on stderr
234 err = err.getvalue()
235 if ('Exception ignored when trying to write to the signal wakeup fd'
236 not in err):
237 raise AssertionError(err)
238 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
239 raise AssertionError(err)
240 else:
241 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200242
243 os.close(r)
244 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200245 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200246 r, w = os.pipe()
247 try:
248 os.write(r, b'x')
249 except OSError:
250 pass
251 else:
252 self.skipTest("OS doesn't report write() error on the read end of a pipe")
253 finally:
254 os.close(r)
255 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200256
257 assert_python_ok('-c', code)
258
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000259 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200260 self.check_wakeup("""def test():
261 import select
262 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000263
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200264 TIMEOUT_FULL = 10
265 TIMEOUT_HALF = 5
266
Victor Stinner749a6a82015-03-30 22:09:14 +0200267 class InterruptSelect(Exception):
268 pass
269
270 def handler(signum, frame):
271 raise InterruptSelect
272 signal.signal(signal.SIGALRM, handler)
273
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200274 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100275
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200276 # We attempt to get a signal during the sleep,
277 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100278 try:
279 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200280 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100281 pass
282 else:
283 raise Exception("select() was not interrupted")
284
285 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200286 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100287 after_time = time.monotonic()
288 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200289 if dt >= TIMEOUT_HALF:
290 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200291 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000292
293 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200294 self.check_wakeup("""def test():
295 import select
296 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000297
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200298 TIMEOUT_FULL = 10
299 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000300
Victor Stinner749a6a82015-03-30 22:09:14 +0200301 class InterruptSelect(Exception):
302 pass
303
304 def handler(signum, frame):
305 raise InterruptSelect
306 signal.signal(signal.SIGALRM, handler)
307
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200308 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100309 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200310 # We attempt to get a signal during the select call
311 try:
312 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200313 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200314 pass
315 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200316 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100317 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200318 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200319 if dt >= TIMEOUT_HALF:
320 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200321 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200322
323 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200324 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200325 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200326 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200327 _testcapi.raise_signal(signal.SIGUSR1)
328 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200329 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000330
Victor Stinnerc13ef662011-05-25 02:35:58 +0200331 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
332 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200333 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200334 self.check_wakeup("""def test():
335 signum1 = signal.SIGUSR1
336 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200337
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200338 signal.signal(signum1, handler)
339 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200340
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200341 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200342 _testcapi.raise_signal(signum1)
343 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200344 # Unblocking the 2 signals calls the C signal handler twice
345 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200346 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200347
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000348
Victor Stinner11517102014-07-29 23:31:34 +0200349@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
350class WakeupSocketSignalTests(unittest.TestCase):
351
352 @unittest.skipIf(_testcapi is None, 'need _testcapi')
353 def test_socket(self):
354 # use a subprocess to have only one thread
355 code = """if 1:
356 import signal
357 import socket
358 import struct
359 import _testcapi
360
361 signum = signal.SIGINT
362 signals = (signum,)
363
364 def handler(signum, frame):
365 pass
366
367 signal.signal(signum, handler)
368
369 read, write = socket.socketpair()
370 read.setblocking(False)
371 write.setblocking(False)
372 signal.set_wakeup_fd(write.fileno())
373
374 _testcapi.raise_signal(signum)
375
376 data = read.recv(1)
377 if not data:
378 raise Exception("no signum written")
379 raised = struct.unpack('B', data)
380 if raised != signals:
381 raise Exception("%r != %r" % (raised, signals))
382
383 read.close()
384 write.close()
385 """
386
387 assert_python_ok('-c', code)
388
389 @unittest.skipIf(_testcapi is None, 'need _testcapi')
390 def test_send_error(self):
391 # Use a subprocess to have only one thread.
392 if os.name == 'nt':
393 action = 'send'
394 else:
395 action = 'write'
396 code = """if 1:
397 import errno
398 import signal
399 import socket
400 import sys
401 import time
402 import _testcapi
403 from test.support import captured_stderr
404
405 signum = signal.SIGINT
406
407 def handler(signum, frame):
408 pass
409
410 signal.signal(signum, handler)
411
412 read, write = socket.socketpair()
413 read.setblocking(False)
414 write.setblocking(False)
415
416 signal.set_wakeup_fd(write.fileno())
417
418 # Close sockets: send() will fail
419 read.close()
420 write.close()
421
422 with captured_stderr() as err:
423 _testcapi.raise_signal(signum)
424
425 err = err.getvalue()
426 if ('Exception ignored when trying to {action} to the signal wakeup fd'
427 not in err):
428 raise AssertionError(err)
429 """.format(action=action)
430 assert_python_ok('-c', code)
431
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800432 @unittest.skipIf(_testcapi is None, 'need _testcapi')
433 def test_warn_on_full_buffer(self):
434 # Use a subprocess to have only one thread.
435 if os.name == 'nt':
436 action = 'send'
437 else:
438 action = 'write'
439 code = """if 1:
440 import errno
441 import signal
442 import socket
443 import sys
444 import time
445 import _testcapi
446 from test.support import captured_stderr
447
448 signum = signal.SIGINT
449
450 # This handler will be called, but we intentionally won't read from
451 # the wakeup fd.
452 def handler(signum, frame):
453 pass
454
455 signal.signal(signum, handler)
456
457 read, write = socket.socketpair()
458 read.setblocking(False)
459 write.setblocking(False)
460
461 # Fill the send buffer
462 try:
463 while True:
464 write.send(b"x")
465 except BlockingIOError:
466 pass
467
468 # By default, we get a warning when a signal arrives
469 signal.set_wakeup_fd(write.fileno())
470
471 with captured_stderr() as err:
472 _testcapi.raise_signal(signum)
473
474 err = err.getvalue()
475 if ('Exception ignored when trying to {action} to the signal wakeup fd'
476 not in err):
477 raise AssertionError(err)
478
479 # And also if warn_on_full_buffer=True
480 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=True)
481
482 with captured_stderr() as err:
483 _testcapi.raise_signal(signum)
484
485 err = err.getvalue()
486 if ('Exception ignored when trying to {action} to the signal wakeup fd'
487 not in err):
488 raise AssertionError(err)
489
490 # But not if warn_on_full_buffer=False
491 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=False)
492
493 with captured_stderr() as err:
494 _testcapi.raise_signal(signum)
495
496 err = err.getvalue()
497 if err != "":
498 raise AssertionError("got unexpected output %r" % (err,))
499
500 # And then check the default again, to make sure warn_on_full_buffer
501 # settings don't leak across calls.
502 signal.set_wakeup_fd(write.fileno())
503
504 with captured_stderr() as err:
505 _testcapi.raise_signal(signum)
506
507 err = err.getvalue()
508 if ('Exception ignored when trying to {action} to the signal wakeup fd'
509 not in err):
510 raise AssertionError(err)
511
512 """.format(action=action)
513 assert_python_ok('-c', code)
514
Victor Stinner11517102014-07-29 23:31:34 +0200515
Brian Curtin3f004b12010-08-06 19:34:52 +0000516@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000517class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000518
Victor Stinnerd6284962011-06-20 23:28:09 +0200519 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000520 """Perform a read during which a signal will arrive. Return True if the
521 read is interrupted by the signal and raises an exception. Return False
522 if it returns normally.
523 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200524 # use a subprocess to have only one thread, to have a timeout on the
525 # blocking read and to not touch signal handling in this process
526 code = """if 1:
527 import errno
528 import os
529 import signal
530 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000531
Victor Stinnerd6284962011-06-20 23:28:09 +0200532 interrupt = %r
533 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000534
Victor Stinnerd6284962011-06-20 23:28:09 +0200535 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000536 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200537
538 signal.signal(signal.SIGALRM, handler)
539 if interrupt is not None:
540 signal.siginterrupt(signal.SIGALRM, interrupt)
541
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200542 print("ready")
543 sys.stdout.flush()
544
Victor Stinnerd6284962011-06-20 23:28:09 +0200545 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200546 try:
547 for loop in range(2):
548 # send a SIGALRM in a second (during the read)
549 signal.alarm(1)
550 try:
551 # blocking call: read from a pipe without data
552 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000553 except ZeroDivisionError:
554 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200555 else:
556 sys.exit(2)
557 sys.exit(3)
558 finally:
559 os.close(r)
560 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200561 """ % (interrupt,)
562 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000563 try:
Victor Stinner45273652011-06-22 22:15:51 +0200564 # wait until the child process is loaded and has started
565 first_line = process.stdout.readline()
566
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200567 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200568 except subprocess.TimeoutExpired:
569 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000570 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200571 else:
Victor Stinner45273652011-06-22 22:15:51 +0200572 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200573 exitcode = process.wait()
574 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200575 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200576 % (exitcode, stdout))
577 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000578
579 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200580 # If a signal handler is installed and siginterrupt is not called
581 # at all, when that signal arrives, it interrupts a syscall that's in
582 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200583 interrupted = self.readpipe_interrupted(None)
584 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000585
586 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200587 # If a signal handler is installed and siginterrupt is called with
588 # a true value for the second argument, when that signal arrives, it
589 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200590 interrupted = self.readpipe_interrupted(True)
591 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000592
593 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200594 # If a signal handler is installed and siginterrupt is called with
595 # a false value for the second argument, when that signal arrives, it
596 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200597 interrupted = self.readpipe_interrupted(False)
598 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000599
600
Brian Curtin3f004b12010-08-06 19:34:52 +0000601@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000602class ItimerTest(unittest.TestCase):
603 def setUp(self):
604 self.hndl_called = False
605 self.hndl_count = 0
606 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000607 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000608
609 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000610 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000611 if self.itimer is not None: # test_itimer_exc doesn't change this attr
612 # just ensure that itimer is stopped
613 signal.setitimer(self.itimer, 0)
614
615 def sig_alrm(self, *args):
616 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000617
618 def sig_vtalrm(self, *args):
619 self.hndl_called = True
620
621 if self.hndl_count > 3:
622 # it shouldn't be here, because it should have been disabled.
623 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
624 "timer.")
625 elif self.hndl_count == 3:
626 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
627 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000628
629 self.hndl_count += 1
630
Martin v. Löwis823725e2008-03-24 13:39:54 +0000631 def sig_prof(self, *args):
632 self.hndl_called = True
633 signal.setitimer(signal.ITIMER_PROF, 0)
634
Martin v. Löwis823725e2008-03-24 13:39:54 +0000635 def test_itimer_exc(self):
636 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
637 # defines it ?
638 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000639 # Negative times are treated as zero on some platforms.
640 if 0:
641 self.assertRaises(signal.ItimerError,
642 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000643
644 def test_itimer_real(self):
645 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000646 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000647 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000648 self.assertEqual(self.hndl_called, True)
649
R. David Murray44546f82010-04-21 01:59:28 +0000650 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner13ff2452018-01-22 18:32:50 +0100651 @unittest.skipIf(sys.platform in ('netbsd5',),
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000652 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000653 def test_itimer_virtual(self):
654 self.itimer = signal.ITIMER_VIRTUAL
655 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
656 signal.setitimer(self.itimer, 0.3, 0.2)
657
Victor Stinner79d68f92015-03-19 21:54:09 +0100658 start_time = time.monotonic()
659 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000660 # use up some virtual time by doing real work
661 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000662 if signal.getitimer(self.itimer) == (0.0, 0.0):
663 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000664 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000665 self.skipTest("timeout: likely cause: machine too slow or load too "
666 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000667
668 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000669 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000670 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000671 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000672
673 def test_itimer_prof(self):
674 self.itimer = signal.ITIMER_PROF
675 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000676 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000677
Victor Stinner79d68f92015-03-19 21:54:09 +0100678 start_time = time.monotonic()
679 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000680 # do some work
681 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000682 if signal.getitimer(self.itimer) == (0.0, 0.0):
683 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000684 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000685 self.skipTest("timeout: likely cause: machine too slow or load too "
686 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000687
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000688 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000689 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000690 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000691 self.assertEqual(self.hndl_called, True)
692
Antoine Pitrou729780a2017-06-30 10:01:05 +0200693 def test_setitimer_tiny(self):
694 # bpo-30807: C setitimer() takes a microsecond-resolution interval.
695 # Check that float -> timeval conversion doesn't round
696 # the interval down to zero, which would disable the timer.
697 self.itimer = signal.ITIMER_REAL
698 signal.setitimer(self.itimer, 1e-6)
699 time.sleep(1)
700 self.assertEqual(self.hndl_called, True)
701
Victor Stinnera9293352011-04-30 15:21:58 +0200702
Victor Stinner35b300c2011-05-04 13:20:35 +0200703class PendingSignalsTests(unittest.TestCase):
704 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200705 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
706 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200707 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200708 @unittest.skipUnless(hasattr(signal, 'sigpending'),
709 'need signal.sigpending()')
710 def test_sigpending_empty(self):
711 self.assertEqual(signal.sigpending(), set())
712
713 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
714 'need signal.pthread_sigmask()')
715 @unittest.skipUnless(hasattr(signal, 'sigpending'),
716 'need signal.sigpending()')
717 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200718 code = """if 1:
719 import os
720 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200721
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200722 def handler(signum, frame):
723 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200724
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200725 signum = signal.SIGUSR1
726 signal.signal(signum, handler)
727
728 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
729 os.kill(os.getpid(), signum)
730 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200731 for sig in pending:
732 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200733 if pending != {signum}:
734 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200735 try:
736 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
737 except ZeroDivisionError:
738 pass
739 else:
740 raise Exception("ZeroDivisionError not raised")
741 """
742 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200743
744 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
745 'need signal.pthread_kill()')
746 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200747 code = """if 1:
748 import signal
749 import threading
750 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200751
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200752 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200753
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200754 def handler(signum, frame):
755 1/0
756
757 signal.signal(signum, handler)
758
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200759 tid = threading.get_ident()
760 try:
761 signal.pthread_kill(tid, 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
Victor Stinner7f294d12011-06-10 14:02:10 +0200769 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
770 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200771 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200772 """
773 test: body of the "def test(signum):" function.
774 blocked: number of the blocked signal
775 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200776 code = '''if 1:
777 import signal
778 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200779 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200780
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200781 def handler(signum, frame):
782 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200783
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200784 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200785
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200786 blocked = %s
787 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200788
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200789 # child: block and wait the signal
790 try:
791 signal.signal(signum, handler)
792 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200793
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200794 # Do the tests
795 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200796
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200797 # The handler must not be called on unblock
798 try:
799 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
800 except ZeroDivisionError:
801 print("the signal handler has been called",
802 file=sys.stderr)
803 sys.exit(1)
804 except BaseException as err:
805 print("error: {}".format(err), file=sys.stderr)
806 sys.stderr.flush()
807 sys.exit(1)
808 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200809
Ross Lagerwallbc808222011-06-25 12:13:40 +0200810 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200811 # process might have several threads running, use a subprocess to have
812 # a single thread.
813 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200814
Victor Stinnerb3e72192011-05-08 01:46:11 +0200815 @unittest.skipUnless(hasattr(signal, 'sigwait'),
816 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200817 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200818 self.wait_helper(signal.SIGALRM, '''
819 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200820 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200821 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200822 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200823 if received != signum:
824 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200825 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200826
827 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
828 'need signal.sigwaitinfo()')
829 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200830 self.wait_helper(signal.SIGALRM, '''
831 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200832 signal.alarm(1)
833 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200834 if info.si_signo != signum:
835 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200836 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200837
838 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
839 'need signal.sigtimedwait()')
840 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200841 self.wait_helper(signal.SIGALRM, '''
842 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200843 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100844 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200845 if info.si_signo != signum:
846 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200847 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200848
Ross Lagerwallbc808222011-06-25 12:13:40 +0200849 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
850 'need signal.sigtimedwait()')
851 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200852 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200853 self.wait_helper(signal.SIGALRM, '''
854 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200855 import os
856 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100857 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200858 if info.si_signo != signum:
859 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200860 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200861
862 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
863 'need signal.sigtimedwait()')
864 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200865 self.wait_helper(signal.SIGALRM, '''
866 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100867 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200868 if received is not None:
869 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200870 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200871
872 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
873 'need signal.sigtimedwait()')
874 def test_sigtimedwait_negative_timeout(self):
875 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100876 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200877
Ross Lagerwallbc808222011-06-25 12:13:40 +0200878 @unittest.skipUnless(hasattr(signal, 'sigwait'),
879 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200880 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
881 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200882 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200883 # Check that calling sigwait() from a thread doesn't suspend the whole
884 # process. A new interpreter is spawned to avoid problems when mixing
885 # threads and fork(): only async-safe functions are allowed between
886 # fork() and exec().
887 assert_python_ok("-c", """if True:
888 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200889
Victor Stinner415007e2011-06-13 16:19:06 +0200890 # the default handler terminates the process
891 signum = signal.SIGUSR1
892
893 def kill_later():
894 # wait until the main thread is waiting in sigwait()
895 time.sleep(1)
896 os.kill(os.getpid(), signum)
897
898 # the signal must be blocked by all the threads
899 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
900 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200901 killer.start()
902 received = signal.sigwait([signum])
903 if received != signum:
904 print("sigwait() received %s, not %s" % (received, signum),
905 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200906 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200907 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200908 # unblock the signal, which should have been cleared by sigwait()
909 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
910 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200911
Victor Stinnerb3e72192011-05-08 01:46:11 +0200912 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
913 'need signal.pthread_sigmask()')
914 def test_pthread_sigmask_arguments(self):
915 self.assertRaises(TypeError, signal.pthread_sigmask)
916 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
917 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
918 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
919
920 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
921 'need signal.pthread_sigmask()')
922 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200923 code = """if 1:
924 import signal
925 import os; import threading
926
927 def handler(signum, frame):
928 1/0
929
930 def kill(signum):
931 os.kill(os.getpid(), signum)
932
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200933 def check_mask(mask):
934 for sig in mask:
935 assert isinstance(sig, signal.Signals), repr(sig)
936
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200937 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200938 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
939 check_mask(sigmask)
940 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200941
Victor Stinnerb3e72192011-05-08 01:46:11 +0200942 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200943
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200944 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200945 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200946
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200947 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200948 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200949 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200950 try:
951 kill(signum)
952 except ZeroDivisionError:
953 pass
954 else:
955 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200956
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200957 # Block and then raise SIGUSR1. The signal is blocked: the signal
958 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200959 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
960 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200961 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200962
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200963 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200964 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200965 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +0200966 if signum not in blocked:
967 raise Exception("%s not in %s" % (signum, blocked))
968 if old_mask ^ blocked != {signum}:
969 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200970
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200971 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200972 try:
R David Murrayfc069992013-12-13 20:52:19 -0500973 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200974 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200975 except ZeroDivisionError:
976 pass
977 else:
978 raise Exception("ZeroDivisionError not raised")
979 try:
980 kill(signum)
981 except ZeroDivisionError:
982 pass
983 else:
984 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200985
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200986 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200987 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200988 if signum in unblocked:
989 raise Exception("%s in %s" % (signum, unblocked))
990 if blocked ^ unblocked != {signum}:
991 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
992 if old_mask != unblocked:
993 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200994 """
995 assert_python_ok('-c', code)
996
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200997 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
998 'need signal.pthread_kill()')
999 def test_pthread_kill_main_thread(self):
1000 # Test that a signal can be sent to the main thread with pthread_kill()
1001 # before any other thread has been created (see issue #12392).
1002 code = """if True:
1003 import threading
1004 import signal
1005 import sys
1006
1007 def handler(signum, frame):
1008 sys.exit(3)
1009
1010 signal.signal(signal.SIGUSR1, handler)
1011 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1012 sys.exit(2)
1013 """
1014
1015 with spawn_python('-c', code) as process:
1016 stdout, stderr = process.communicate()
1017 exitcode = process.wait()
1018 if exitcode != 3:
1019 raise Exception("Child error (exit code %s): %s" %
1020 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001021
1022
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001023class StressTest(unittest.TestCase):
1024 """
1025 Stress signal delivery, especially when a signal arrives in
1026 the middle of recomputing the signal state or executing
1027 previously tripped signal handlers.
1028 """
1029
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001030 def setsig(self, signum, handler):
1031 old_handler = signal.signal(signum, handler)
1032 self.addCleanup(signal.signal, signum, old_handler)
1033
1034 def measure_itimer_resolution(self):
1035 N = 20
1036 times = []
1037
1038 def handler(signum=None, frame=None):
1039 if len(times) < N:
1040 times.append(time.perf_counter())
1041 # 1 µs is the smallest possible timer interval,
1042 # we want to measure what the concrete duration
1043 # will be on this platform
1044 signal.setitimer(signal.ITIMER_REAL, 1e-6)
1045
1046 self.addCleanup(signal.setitimer, signal.ITIMER_REAL, 0)
1047 self.setsig(signal.SIGALRM, handler)
1048 handler()
1049 while len(times) < N:
1050 time.sleep(1e-3)
1051
1052 durations = [times[i+1] - times[i] for i in range(len(times) - 1)]
1053 med = statistics.median(durations)
1054 if support.verbose:
1055 print("detected median itimer() resolution: %.6f s." % (med,))
1056 return med
1057
1058 def decide_itimer_count(self):
1059 # Some systems have poor setitimer() resolution (for example
1060 # measured around 20 ms. on FreeBSD 9), so decide on a reasonable
1061 # number of sequential timers based on that.
1062 reso = self.measure_itimer_resolution()
1063 if reso <= 1e-4:
1064 return 10000
1065 elif reso <= 1e-2:
1066 return 100
1067 else:
1068 self.skipTest("detected itimer resolution (%.3f s.) too high "
1069 "(> 10 ms.) on this platform (or system too busy)"
1070 % (reso,))
1071
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001072 @unittest.skipUnless(hasattr(signal, "setitimer"),
1073 "test needs setitimer()")
1074 def test_stress_delivery_dependent(self):
1075 """
1076 This test uses dependent signal handlers.
1077 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001078 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001079 sigs = []
1080
1081 def first_handler(signum, frame):
1082 # 1e-6 is the minimum non-zero value for `setitimer()`.
1083 # Choose a random delay so as to improve chances of
1084 # triggering a race condition. Ideally the signal is received
1085 # when inside critical signal-handling routines such as
1086 # Py_MakePendingCalls().
1087 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1088
1089 def second_handler(signum=None, frame=None):
1090 sigs.append(signum)
1091
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001092 # Here on Linux, SIGPROF > SIGALRM > SIGUSR1. By using both
1093 # ascending and descending sequences (SIGUSR1 then SIGALRM,
1094 # SIGPROF then SIGALRM), we maximize chances of hitting a bug.
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001095 self.setsig(signal.SIGPROF, first_handler)
1096 self.setsig(signal.SIGUSR1, first_handler)
1097 self.setsig(signal.SIGALRM, second_handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001098
1099 expected_sigs = 0
1100 deadline = time.time() + 15.0
1101
1102 while expected_sigs < N:
1103 os.kill(os.getpid(), signal.SIGPROF)
1104 expected_sigs += 1
1105 # Wait for handlers to run to avoid signal coalescing
1106 while len(sigs) < expected_sigs and time.time() < deadline:
1107 time.sleep(1e-5)
1108
1109 os.kill(os.getpid(), signal.SIGUSR1)
1110 expected_sigs += 1
1111 while len(sigs) < expected_sigs and time.time() < deadline:
1112 time.sleep(1e-5)
1113
1114 # All ITIMER_REAL signals should have been delivered to the
1115 # Python handler
1116 self.assertEqual(len(sigs), N, "Some signals were lost")
1117
1118 @unittest.skipUnless(hasattr(signal, "setitimer"),
1119 "test needs setitimer()")
1120 def test_stress_delivery_simultaneous(self):
1121 """
1122 This test uses simultaneous signal handlers.
1123 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001124 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001125 sigs = []
1126
1127 def handler(signum, frame):
1128 sigs.append(signum)
1129
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001130 self.setsig(signal.SIGUSR1, handler)
1131 self.setsig(signal.SIGALRM, handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001132
1133 expected_sigs = 0
1134 deadline = time.time() + 15.0
1135
1136 while expected_sigs < N:
1137 # Hopefully the SIGALRM will be received somewhere during
1138 # initial processing of SIGUSR1.
1139 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1140 os.kill(os.getpid(), signal.SIGUSR1)
1141
1142 expected_sigs += 2
1143 # Wait for handlers to run to avoid signal coalescing
1144 while len(sigs) < expected_sigs and time.time() < deadline:
1145 time.sleep(1e-5)
1146
1147 # All ITIMER_REAL signals should have been delivered to the
1148 # Python handler
1149 self.assertEqual(len(sigs), N, "Some signals were lost")
1150
1151
Zachary Ware38c707e2015-04-13 15:00:43 -05001152def tearDownModule():
1153 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001154
1155if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001156 unittest.main()