blob: 6a43fe70372c55aebea14d1ba091e8e4517440ab [file] [log] [blame]
Vladimir Matveevc24c6c22019-01-08 01:58:25 -08001import errno
Victor Stinnerd6debb22017-03-27 16:05:26 +02002import os
Antoine Pitrouc08177a2017-06-28 23:29:29 +02003import random
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00004import signal
Victor Stinner11517102014-07-29 23:31:34 +02005import socket
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02006import statistics
Christian Heimes4fbc72b2008-03-22 00:47:35 +00007import subprocess
Victor Stinnerd6debb22017-03-27 16:05:26 +02008import sys
9import time
10import unittest
11from test import support
Hai Shia7f5d932020-08-04 00:41:24 +080012from test.support import os_helper
Berker Peksagce643912015-05-06 06:33:17 +030013from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020014try:
Victor Stinner56e8c292014-07-21 12:30:22 +020015 import _testcapi
16except ImportError:
17 _testcapi = None
Christian Heimesc06950e2008-02-28 21:17:00 +000018
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000019
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020020class GenericTests(unittest.TestCase):
21
22 def test_enums(self):
23 for name in dir(signal):
24 sig = getattr(signal, name)
25 if name in {'SIG_DFL', 'SIG_IGN'}:
26 self.assertIsInstance(sig, signal.Handlers)
27 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
28 self.assertIsInstance(sig, signal.Sigmasks)
29 elif name.startswith('SIG') and not name.startswith('SIG_'):
30 self.assertIsInstance(sig, signal.Signals)
31 elif name.startswith('CTRL_'):
32 self.assertIsInstance(sig, signal.Signals)
33 self.assertEqual(sys.platform, "win32")
34
35
Brian Curtin3f004b12010-08-06 19:34:52 +000036@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +020037class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +000038 def trivial_signal_handler(self, *args):
39 pass
40
Thomas Woutersed03b412007-08-28 21:37:11 +000041 def test_out_of_range_signal_number_raises_error(self):
42 self.assertRaises(ValueError, signal.getsignal, 4242)
43
Thomas Woutersed03b412007-08-28 21:37:11 +000044 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +000045 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +000046
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010047 self.assertRaises(ValueError, signal.strsignal, 4242)
48
Thomas Woutersed03b412007-08-28 21:37:11 +000049 def test_setting_signal_handler_to_none_raises_error(self):
50 self.assertRaises(TypeError, signal.signal,
51 signal.SIGUSR1, None)
52
Christian Heimes4fbc72b2008-03-22 00:47:35 +000053 def test_getsignal(self):
54 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020055 self.assertIsInstance(hup, signal.Handlers)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000056 self.assertEqual(signal.getsignal(signal.SIGHUP),
57 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000058 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000059 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000060
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010061 def test_strsignal(self):
Antoine Pietri019f5b32018-03-12 20:03:14 +010062 self.assertIn("Interrupt", signal.strsignal(signal.SIGINT))
63 self.assertIn("Terminated", signal.strsignal(signal.SIGTERM))
Michael Osipov48ce4892018-08-23 15:27:19 +020064 self.assertIn("Hangup", signal.strsignal(signal.SIGHUP))
Antoine Pietri5d2a27d2018-03-12 14:42:34 +010065
Victor Stinner32eb8402016-03-15 11:12:35 +010066 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner32eb8402016-03-15 11:12:35 +010067 def test_interprocess_signal(self):
68 dirname = os.path.dirname(__file__)
69 script = os.path.join(dirname, 'signalinterproctester.py')
70 assert_python_ok(script)
71
Antoine Pitrou9d3627e2018-05-04 13:00:50 +020072 def test_valid_signals(self):
73 s = signal.valid_signals()
74 self.assertIsInstance(s, set)
75 self.assertIn(signal.Signals.SIGINT, s)
76 self.assertIn(signal.Signals.SIGALRM, s)
77 self.assertNotIn(0, s)
78 self.assertNotIn(signal.NSIG, s)
79 self.assertLess(len(s), signal.NSIG)
80
Gregory P. Smith38f11cc2019-02-16 12:57:40 -080081 @unittest.skipUnless(sys.executable, "sys.executable required.")
82 def test_keyboard_interrupt_exit_code(self):
83 """KeyboardInterrupt triggers exit via SIGINT."""
84 process = subprocess.run(
85 [sys.executable, "-c",
Gregory P. Smith414c6252019-02-16 17:22:39 -080086 "import os, signal, time\n"
87 "os.kill(os.getpid(), signal.SIGINT)\n"
88 "for _ in range(999): time.sleep(0.01)"],
Gregory P. Smith38f11cc2019-02-16 12:57:40 -080089 stderr=subprocess.PIPE)
90 self.assertIn(b"KeyboardInterrupt", process.stderr)
91 self.assertEqual(process.returncode, -signal.SIGINT)
Gregory P. Smith414c6252019-02-16 17:22:39 -080092 # Caveat: The exit code is insufficient to guarantee we actually died
93 # via a signal. POSIX shells do more than look at the 8 bit value.
94 # Writing an automation friendly test of an interactive shell
95 # to confirm that our process died via a SIGINT proved too complex.
Gregory P. Smith38f11cc2019-02-16 12:57:40 -080096
Christian Heimes4fbc72b2008-03-22 00:47:35 +000097
Brian Curtin3f004b12010-08-06 19:34:52 +000098@unittest.skipUnless(sys.platform == "win32", "Windows specific")
99class WindowsSignalTests(unittest.TestCase):
Antoine Pitrou9d3627e2018-05-04 13:00:50 +0200100
101 def test_valid_signals(self):
102 s = signal.valid_signals()
103 self.assertIsInstance(s, set)
104 self.assertGreaterEqual(len(s), 6)
105 self.assertIn(signal.Signals.SIGINT, s)
106 self.assertNotIn(0, s)
107 self.assertNotIn(signal.NSIG, s)
108 self.assertLess(len(s), signal.NSIG)
109
Brian Curtin3f004b12010-08-06 19:34:52 +0000110 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000111 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000112 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000113 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +0000114 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
115 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
116 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000117 # Set and then reset a handler for signals that work on windows.
118 # Issue #18396, only for signals without a C-level handler.
119 if signal.getsignal(sig) is not None:
120 signal.signal(sig, signal.signal(sig, handler))
121 checked.add(sig)
122 # Issue #18396: Ensure the above loop at least tested *something*
123 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +0000124
125 with self.assertRaises(ValueError):
126 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000127
128 with self.assertRaises(ValueError):
129 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000130
Gregory P. Smith38f11cc2019-02-16 12:57:40 -0800131 @unittest.skipUnless(sys.executable, "sys.executable required.")
132 def test_keyboard_interrupt_exit_code(self):
133 """KeyboardInterrupt triggers an exit using STATUS_CONTROL_C_EXIT."""
134 # We don't test via os.kill(os.getpid(), signal.CTRL_C_EVENT) here
135 # as that requires setting up a console control handler in a child
136 # in its own process group. Doable, but quite complicated. (see
137 # @eryksun on https://github.com/python/cpython/pull/11862)
138 process = subprocess.run(
139 [sys.executable, "-c", "raise KeyboardInterrupt"],
140 stderr=subprocess.PIPE)
141 self.assertIn(b"KeyboardInterrupt", process.stderr)
142 STATUS_CONTROL_C_EXIT = 0xC000013A
143 self.assertEqual(process.returncode, STATUS_CONTROL_C_EXIT)
144
Brian Curtin3f004b12010-08-06 19:34:52 +0000145
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500146class WakeupFDTests(unittest.TestCase):
147
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800148 def test_invalid_call(self):
149 # First parameter is positional-only
150 with self.assertRaises(TypeError):
151 signal.set_wakeup_fd(signum=signal.SIGINT)
152
153 # warn_on_full_buffer is a keyword-only parameter
154 with self.assertRaises(TypeError):
155 signal.set_wakeup_fd(signal.SIGINT, False)
156
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500157 def test_invalid_fd(self):
Hai Shia7f5d932020-08-04 00:41:24 +0800158 fd = os_helper.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +0200159 self.assertRaises((ValueError, OSError),
160 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500161
Victor Stinner11517102014-07-29 23:31:34 +0200162 def test_invalid_socket(self):
163 sock = socket.socket()
164 fd = sock.fileno()
165 sock.close()
166 self.assertRaises((ValueError, OSError),
167 signal.set_wakeup_fd, fd)
168
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200169 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200170 r1, w1 = os.pipe()
171 self.addCleanup(os.close, r1)
172 self.addCleanup(os.close, w1)
173 r2, w2 = os.pipe()
174 self.addCleanup(os.close, r2)
175 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200176
Victor Stinner7cea44d2014-08-27 14:02:36 +0200177 if hasattr(os, 'set_blocking'):
178 os.set_blocking(w1, False)
179 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200180
Victor Stinner1d8948e2014-07-24 22:51:05 +0200181 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200182 self.assertEqual(signal.set_wakeup_fd(w2), w1)
183 self.assertEqual(signal.set_wakeup_fd(-1), w2)
184 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200185
Victor Stinner11517102014-07-29 23:31:34 +0200186 def test_set_wakeup_fd_socket_result(self):
187 sock1 = socket.socket()
188 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200189 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200190 fd1 = sock1.fileno()
191
192 sock2 = socket.socket()
193 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200194 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200195 fd2 = sock2.fileno()
196
197 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200198 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
199 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
200 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200201
Victor Stinner38227602014-08-27 12:59:44 +0200202 # On Windows, files are always blocking and Windows does not provide a
203 # function to test if a socket is in non-blocking mode.
204 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
205 def test_set_wakeup_fd_blocking(self):
206 rfd, wfd = os.pipe()
207 self.addCleanup(os.close, rfd)
208 self.addCleanup(os.close, wfd)
209
210 # fd must be non-blocking
211 os.set_blocking(wfd, True)
212 with self.assertRaises(ValueError) as cm:
213 signal.set_wakeup_fd(wfd)
214 self.assertEqual(str(cm.exception),
215 "the fd %s must be in non-blocking mode" % wfd)
216
217 # non-blocking is ok
218 os.set_blocking(wfd, False)
219 signal.set_wakeup_fd(wfd)
220 signal.set_wakeup_fd(-1)
221
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500222
Brian Curtin3f004b12010-08-06 19:34:52 +0000223@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000224class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200225 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200226 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200227 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200228 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200229 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200230 import os
231 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200232 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000233
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200234 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200235
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200236 def handler(signum, frame):
237 pass
238
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200239 def check_signum(signals):
240 data = os.read(read, len(signals)+1)
241 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200242 if not {!r}:
243 raised = set(raised)
244 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200245 if raised != signals:
246 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200247
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200248 {}
249
250 signal.signal(signal.SIGALRM, handler)
251 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200252 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200253 signal.set_wakeup_fd(write)
254
255 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200256 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200257
258 os.close(read)
259 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200260 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200261
262 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200263
Victor Stinner56e8c292014-07-21 12:30:22 +0200264 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200265 def test_wakeup_write_error(self):
266 # Issue #16105: write() errors in the C signal handler should not
267 # pass silently.
268 # Use a subprocess to have only one thread.
269 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200270 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200271 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200272 import os
273 import signal
274 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200275 from test.support import captured_stderr
276
277 def handler(signum, frame):
278 1/0
279
280 signal.signal(signal.SIGALRM, handler)
281 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200282 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200283
284 # Set wakeup_fd a read-only file descriptor to trigger the error
285 signal.set_wakeup_fd(r)
286 try:
287 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800288 signal.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200289 except ZeroDivisionError:
290 # An ignored exception should have been printed out on stderr
291 err = err.getvalue()
292 if ('Exception ignored when trying to write to the signal wakeup fd'
293 not in err):
294 raise AssertionError(err)
295 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
296 raise AssertionError(err)
297 else:
298 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200299
300 os.close(r)
301 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200302 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200303 r, w = os.pipe()
304 try:
305 os.write(r, b'x')
306 except OSError:
307 pass
308 else:
309 self.skipTest("OS doesn't report write() error on the read end of a pipe")
310 finally:
311 os.close(r)
312 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200313
314 assert_python_ok('-c', code)
315
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000316 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200317 self.check_wakeup("""def test():
318 import select
319 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000320
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200321 TIMEOUT_FULL = 10
322 TIMEOUT_HALF = 5
323
Victor Stinner749a6a82015-03-30 22:09:14 +0200324 class InterruptSelect(Exception):
325 pass
326
327 def handler(signum, frame):
328 raise InterruptSelect
329 signal.signal(signal.SIGALRM, handler)
330
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200331 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100332
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200333 # We attempt to get a signal during the sleep,
334 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100335 try:
336 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200337 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100338 pass
339 else:
340 raise Exception("select() was not interrupted")
341
342 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200343 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100344 after_time = time.monotonic()
345 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200346 if dt >= TIMEOUT_HALF:
347 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200348 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000349
350 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200351 self.check_wakeup("""def test():
352 import select
353 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000354
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200355 TIMEOUT_FULL = 10
356 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000357
Victor Stinner749a6a82015-03-30 22:09:14 +0200358 class InterruptSelect(Exception):
359 pass
360
361 def handler(signum, frame):
362 raise InterruptSelect
363 signal.signal(signal.SIGALRM, handler)
364
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200365 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100366 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200367 # We attempt to get a signal during the select call
368 try:
369 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200370 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200371 pass
372 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200373 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100374 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200375 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200376 if dt >= TIMEOUT_HALF:
377 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200378 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200379
380 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200381 self.check_wakeup("""def test():
382 signal.signal(signal.SIGUSR1, handler)
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800383 signal.raise_signal(signal.SIGUSR1)
384 signal.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200385 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000386
Victor Stinnerc13ef662011-05-25 02:35:58 +0200387 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
388 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200389 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200390 self.check_wakeup("""def test():
391 signum1 = signal.SIGUSR1
392 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200393
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200394 signal.signal(signum1, handler)
395 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200396
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200397 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800398 signal.raise_signal(signum1)
399 signal.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200400 # Unblocking the 2 signals calls the C signal handler twice
401 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200402 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200403
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000404
Victor Stinner11517102014-07-29 23:31:34 +0200405@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
406class WakeupSocketSignalTests(unittest.TestCase):
407
408 @unittest.skipIf(_testcapi is None, 'need _testcapi')
409 def test_socket(self):
410 # use a subprocess to have only one thread
411 code = """if 1:
412 import signal
413 import socket
414 import struct
415 import _testcapi
416
417 signum = signal.SIGINT
418 signals = (signum,)
419
420 def handler(signum, frame):
421 pass
422
423 signal.signal(signum, handler)
424
425 read, write = socket.socketpair()
Victor Stinner11517102014-07-29 23:31:34 +0200426 write.setblocking(False)
427 signal.set_wakeup_fd(write.fileno())
428
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800429 signal.raise_signal(signum)
Victor Stinner11517102014-07-29 23:31:34 +0200430
431 data = read.recv(1)
432 if not data:
433 raise Exception("no signum written")
434 raised = struct.unpack('B', data)
435 if raised != signals:
436 raise Exception("%r != %r" % (raised, signals))
437
438 read.close()
439 write.close()
440 """
441
442 assert_python_ok('-c', code)
443
444 @unittest.skipIf(_testcapi is None, 'need _testcapi')
445 def test_send_error(self):
446 # Use a subprocess to have only one thread.
447 if os.name == 'nt':
448 action = 'send'
449 else:
450 action = 'write'
451 code = """if 1:
452 import errno
453 import signal
454 import socket
455 import sys
456 import time
457 import _testcapi
458 from test.support import captured_stderr
459
460 signum = signal.SIGINT
461
462 def handler(signum, frame):
463 pass
464
465 signal.signal(signum, handler)
466
467 read, write = socket.socketpair()
468 read.setblocking(False)
469 write.setblocking(False)
470
471 signal.set_wakeup_fd(write.fileno())
472
473 # Close sockets: send() will fail
474 read.close()
475 write.close()
476
477 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800478 signal.raise_signal(signum)
Victor Stinner11517102014-07-29 23:31:34 +0200479
480 err = err.getvalue()
481 if ('Exception ignored when trying to {action} to the signal wakeup fd'
482 not in err):
483 raise AssertionError(err)
484 """.format(action=action)
485 assert_python_ok('-c', code)
486
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800487 @unittest.skipIf(_testcapi is None, 'need _testcapi')
488 def test_warn_on_full_buffer(self):
489 # Use a subprocess to have only one thread.
490 if os.name == 'nt':
491 action = 'send'
492 else:
493 action = 'write'
494 code = """if 1:
495 import errno
496 import signal
497 import socket
498 import sys
499 import time
500 import _testcapi
501 from test.support import captured_stderr
502
503 signum = signal.SIGINT
504
505 # This handler will be called, but we intentionally won't read from
506 # the wakeup fd.
507 def handler(signum, frame):
508 pass
509
510 signal.signal(signum, handler)
511
512 read, write = socket.socketpair()
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800513
Victor Stinner686b4b52018-07-18 18:29:54 +0200514 # Fill the socketpair buffer
515 if sys.platform == 'win32':
516 # bpo-34130: On Windows, sometimes non-blocking send fails to fill
517 # the full socketpair buffer, so use a timeout of 50 ms instead.
518 write.settimeout(0.050)
519 else:
520 write.setblocking(False)
521
Victor Stinner686b4b52018-07-18 18:29:54 +0200522 written = 0
pxinwr1244c812020-12-01 05:48:33 +0800523 if sys.platform == "vxworks":
524 CHUNK_SIZES = (1,)
525 else:
526 # Start with large chunk size to reduce the
527 # number of send needed to fill the buffer.
528 CHUNK_SIZES = (2 ** 16, 2 ** 8, 1)
529 for chunk_size in CHUNK_SIZES:
Victor Stinner686b4b52018-07-18 18:29:54 +0200530 chunk = b"x" * chunk_size
531 try:
532 while True:
533 write.send(chunk)
534 written += chunk_size
Christian Heimes03c8ddd2020-11-20 09:26:07 +0100535 except (BlockingIOError, TimeoutError):
Victor Stinner686b4b52018-07-18 18:29:54 +0200536 pass
537
538 print(f"%s bytes written into the socketpair" % written, flush=True)
539
540 write.setblocking(False)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800541 try:
Victor Stinner686b4b52018-07-18 18:29:54 +0200542 write.send(b"x")
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800543 except BlockingIOError:
Victor Stinner686b4b52018-07-18 18:29:54 +0200544 # The socketpair buffer seems full
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800545 pass
Victor Stinner686b4b52018-07-18 18:29:54 +0200546 else:
547 raise AssertionError("%s bytes failed to fill the socketpair "
548 "buffer" % written)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800549
550 # By default, we get a warning when a signal arrives
Victor Stinner686b4b52018-07-18 18:29:54 +0200551 msg = ('Exception ignored when trying to {action} '
552 'to the signal wakeup fd')
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800553 signal.set_wakeup_fd(write.fileno())
554
555 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800556 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800557
558 err = err.getvalue()
Victor Stinner686b4b52018-07-18 18:29:54 +0200559 if msg not in err:
560 raise AssertionError("first set_wakeup_fd() test failed, "
561 "stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800562
563 # And also if warn_on_full_buffer=True
564 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=True)
565
566 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800567 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800568
569 err = err.getvalue()
Victor Stinner686b4b52018-07-18 18:29:54 +0200570 if msg not in err:
571 raise AssertionError("set_wakeup_fd(warn_on_full_buffer=True) "
572 "test failed, stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800573
574 # But not if warn_on_full_buffer=False
575 signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=False)
576
577 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800578 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800579
580 err = err.getvalue()
581 if err != "":
Victor Stinner686b4b52018-07-18 18:29:54 +0200582 raise AssertionError("set_wakeup_fd(warn_on_full_buffer=False) "
583 "test failed, stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800584
585 # And then check the default again, to make sure warn_on_full_buffer
586 # settings don't leak across calls.
587 signal.set_wakeup_fd(write.fileno())
588
589 with captured_stderr() as err:
Vladimir Matveevc24c6c22019-01-08 01:58:25 -0800590 signal.raise_signal(signum)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800591
592 err = err.getvalue()
Victor Stinner686b4b52018-07-18 18:29:54 +0200593 if msg not in err:
594 raise AssertionError("second set_wakeup_fd() test failed, "
595 "stderr: %r" % err)
Nathaniel J. Smith902ab802017-12-17 20:10:18 -0800596
597 """.format(action=action)
598 assert_python_ok('-c', code)
599
Victor Stinner11517102014-07-29 23:31:34 +0200600
Brian Curtin3f004b12010-08-06 19:34:52 +0000601@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
pxinwr1244c812020-12-01 05:48:33 +0800602@unittest.skipUnless(hasattr(signal, 'siginterrupt'), "needs signal.siginterrupt()")
Christian Heimes8640e742008-02-23 16:23:06 +0000603class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000604
Victor Stinnerd6284962011-06-20 23:28:09 +0200605 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000606 """Perform a read during which a signal will arrive. Return True if the
607 read is interrupted by the signal and raises an exception. Return False
608 if it returns normally.
609 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200610 # use a subprocess to have only one thread, to have a timeout on the
611 # blocking read and to not touch signal handling in this process
612 code = """if 1:
613 import errno
614 import os
615 import signal
616 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000617
Victor Stinnerd6284962011-06-20 23:28:09 +0200618 interrupt = %r
619 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000620
Victor Stinnerd6284962011-06-20 23:28:09 +0200621 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000622 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200623
624 signal.signal(signal.SIGALRM, handler)
625 if interrupt is not None:
626 signal.siginterrupt(signal.SIGALRM, interrupt)
627
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200628 print("ready")
629 sys.stdout.flush()
630
Victor Stinnerd6284962011-06-20 23:28:09 +0200631 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200632 try:
633 for loop in range(2):
634 # send a SIGALRM in a second (during the read)
635 signal.alarm(1)
636 try:
637 # blocking call: read from a pipe without data
638 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000639 except ZeroDivisionError:
640 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200641 else:
642 sys.exit(2)
643 sys.exit(3)
644 finally:
645 os.close(r)
646 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200647 """ % (interrupt,)
648 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000649 try:
Victor Stinner45273652011-06-22 22:15:51 +0200650 # wait until the child process is loaded and has started
651 first_line = process.stdout.readline()
652
Victor Stinner0d63bac2019-12-11 11:30:03 +0100653 stdout, stderr = process.communicate(timeout=support.SHORT_TIMEOUT)
Victor Stinnerd6284962011-06-20 23:28:09 +0200654 except subprocess.TimeoutExpired:
655 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000656 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200657 else:
Victor Stinner45273652011-06-22 22:15:51 +0200658 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200659 exitcode = process.wait()
660 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200661 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200662 % (exitcode, stdout))
663 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000664
665 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200666 # If a signal handler is installed and siginterrupt is not called
667 # at all, when that signal arrives, it interrupts a syscall that's in
668 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200669 interrupted = self.readpipe_interrupted(None)
670 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000671
672 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200673 # If a signal handler is installed and siginterrupt is called with
674 # a true value for the second argument, when that signal arrives, it
675 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200676 interrupted = self.readpipe_interrupted(True)
677 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000678
679 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200680 # If a signal handler is installed and siginterrupt is called with
681 # a false value for the second argument, when that signal arrives, it
682 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200683 interrupted = self.readpipe_interrupted(False)
684 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000685
686
Brian Curtin3f004b12010-08-06 19:34:52 +0000687@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
pxinwr1244c812020-12-01 05:48:33 +0800688@unittest.skipUnless(hasattr(signal, 'getitimer') and hasattr(signal, 'setitimer'),
689 "needs signal.getitimer() and signal.setitimer()")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000690class ItimerTest(unittest.TestCase):
691 def setUp(self):
692 self.hndl_called = False
693 self.hndl_count = 0
694 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000695 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000696
697 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000698 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000699 if self.itimer is not None: # test_itimer_exc doesn't change this attr
700 # just ensure that itimer is stopped
701 signal.setitimer(self.itimer, 0)
702
703 def sig_alrm(self, *args):
704 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000705
706 def sig_vtalrm(self, *args):
707 self.hndl_called = True
708
709 if self.hndl_count > 3:
710 # it shouldn't be here, because it should have been disabled.
711 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
712 "timer.")
713 elif self.hndl_count == 3:
714 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
715 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000716
717 self.hndl_count += 1
718
Martin v. Löwis823725e2008-03-24 13:39:54 +0000719 def sig_prof(self, *args):
720 self.hndl_called = True
721 signal.setitimer(signal.ITIMER_PROF, 0)
722
Martin v. Löwis823725e2008-03-24 13:39:54 +0000723 def test_itimer_exc(self):
724 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
725 # defines it ?
726 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000727 # Negative times are treated as zero on some platforms.
728 if 0:
729 self.assertRaises(signal.ItimerError,
730 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000731
732 def test_itimer_real(self):
733 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000734 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000735 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000736 self.assertEqual(self.hndl_called, True)
737
R. David Murray44546f82010-04-21 01:59:28 +0000738 # Issue 3864, unknown if this affects earlier versions of freebsd also
Victor Stinner13ff2452018-01-22 18:32:50 +0100739 @unittest.skipIf(sys.platform in ('netbsd5',),
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000740 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000741 def test_itimer_virtual(self):
742 self.itimer = signal.ITIMER_VIRTUAL
743 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
744 signal.setitimer(self.itimer, 0.3, 0.2)
745
Victor Stinner79d68f92015-03-19 21:54:09 +0100746 start_time = time.monotonic()
747 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000748 # use up some virtual time by doing real work
749 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000750 if signal.getitimer(self.itimer) == (0.0, 0.0):
751 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000752 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000753 self.skipTest("timeout: likely cause: machine too slow or load too "
754 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000755
756 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000757 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000758 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000759 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000760
761 def test_itimer_prof(self):
762 self.itimer = signal.ITIMER_PROF
763 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000764 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000765
Victor Stinner79d68f92015-03-19 21:54:09 +0100766 start_time = time.monotonic()
767 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000768 # do some work
769 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000770 if signal.getitimer(self.itimer) == (0.0, 0.0):
771 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000772 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000773 self.skipTest("timeout: likely cause: machine too slow or load too "
774 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000775
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000776 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000777 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000778 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000779 self.assertEqual(self.hndl_called, True)
780
Antoine Pitrou729780a2017-06-30 10:01:05 +0200781 def test_setitimer_tiny(self):
782 # bpo-30807: C setitimer() takes a microsecond-resolution interval.
783 # Check that float -> timeval conversion doesn't round
784 # the interval down to zero, which would disable the timer.
785 self.itimer = signal.ITIMER_REAL
786 signal.setitimer(self.itimer, 1e-6)
787 time.sleep(1)
788 self.assertEqual(self.hndl_called, True)
789
Victor Stinnera9293352011-04-30 15:21:58 +0200790
Victor Stinner35b300c2011-05-04 13:20:35 +0200791class PendingSignalsTests(unittest.TestCase):
792 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200793 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
794 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200795 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200796 @unittest.skipUnless(hasattr(signal, 'sigpending'),
797 'need signal.sigpending()')
798 def test_sigpending_empty(self):
799 self.assertEqual(signal.sigpending(), set())
800
801 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
802 'need signal.pthread_sigmask()')
803 @unittest.skipUnless(hasattr(signal, 'sigpending'),
804 'need signal.sigpending()')
805 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200806 code = """if 1:
807 import os
808 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200809
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200810 def handler(signum, frame):
811 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200812
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200813 signum = signal.SIGUSR1
814 signal.signal(signum, handler)
815
816 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
817 os.kill(os.getpid(), signum)
818 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200819 for sig in pending:
820 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200821 if pending != {signum}:
822 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200823 try:
824 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
825 except ZeroDivisionError:
826 pass
827 else:
828 raise Exception("ZeroDivisionError not raised")
829 """
830 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200831
832 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
833 'need signal.pthread_kill()')
834 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200835 code = """if 1:
836 import signal
837 import threading
838 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200839
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200840 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200841
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200842 def handler(signum, frame):
843 1/0
844
845 signal.signal(signum, handler)
846
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200847 tid = threading.get_ident()
848 try:
849 signal.pthread_kill(tid, signum)
850 except ZeroDivisionError:
851 pass
852 else:
853 raise Exception("ZeroDivisionError not raised")
854 """
855 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200856
Victor Stinner7f294d12011-06-10 14:02:10 +0200857 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
858 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200859 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200860 """
861 test: body of the "def test(signum):" function.
862 blocked: number of the blocked signal
863 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200864 code = '''if 1:
865 import signal
866 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200867 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200868
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200869 def handler(signum, frame):
870 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200871
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200872 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200873
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200874 blocked = %s
875 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200876
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200877 # child: block and wait the signal
878 try:
879 signal.signal(signum, handler)
880 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200881
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200882 # Do the tests
883 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200884
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200885 # The handler must not be called on unblock
886 try:
887 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
888 except ZeroDivisionError:
889 print("the signal handler has been called",
890 file=sys.stderr)
891 sys.exit(1)
892 except BaseException as err:
893 print("error: {}".format(err), file=sys.stderr)
894 sys.stderr.flush()
895 sys.exit(1)
896 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200897
Ross Lagerwallbc808222011-06-25 12:13:40 +0200898 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200899 # process might have several threads running, use a subprocess to have
900 # a single thread.
901 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200902
Victor Stinnerb3e72192011-05-08 01:46:11 +0200903 @unittest.skipUnless(hasattr(signal, 'sigwait'),
904 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200905 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200906 self.wait_helper(signal.SIGALRM, '''
907 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200908 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200909 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200910 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200911 if received != signum:
912 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200913 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200914
915 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
916 'need signal.sigwaitinfo()')
917 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200918 self.wait_helper(signal.SIGALRM, '''
919 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200920 signal.alarm(1)
921 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200922 if info.si_signo != signum:
923 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200924 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200925
926 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
927 'need signal.sigtimedwait()')
928 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200929 self.wait_helper(signal.SIGALRM, '''
930 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200931 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100932 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200933 if info.si_signo != signum:
934 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200935 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200936
Ross Lagerwallbc808222011-06-25 12:13:40 +0200937 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
938 'need signal.sigtimedwait()')
939 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200940 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200941 self.wait_helper(signal.SIGALRM, '''
942 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200943 import os
944 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100945 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200946 if info.si_signo != signum:
947 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200948 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200949
950 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
951 'need signal.sigtimedwait()')
952 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200953 self.wait_helper(signal.SIGALRM, '''
954 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100955 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200956 if received is not None:
957 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200958 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200959
960 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
961 'need signal.sigtimedwait()')
962 def test_sigtimedwait_negative_timeout(self):
963 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100964 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200965
Ross Lagerwallbc808222011-06-25 12:13:40 +0200966 @unittest.skipUnless(hasattr(signal, 'sigwait'),
967 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200968 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
969 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200970 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200971 # Check that calling sigwait() from a thread doesn't suspend the whole
972 # process. A new interpreter is spawned to avoid problems when mixing
973 # threads and fork(): only async-safe functions are allowed between
974 # fork() and exec().
975 assert_python_ok("-c", """if True:
976 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200977
Victor Stinner415007e2011-06-13 16:19:06 +0200978 # the default handler terminates the process
979 signum = signal.SIGUSR1
980
981 def kill_later():
982 # wait until the main thread is waiting in sigwait()
983 time.sleep(1)
984 os.kill(os.getpid(), signum)
985
986 # the signal must be blocked by all the threads
987 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
988 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200989 killer.start()
990 received = signal.sigwait([signum])
991 if received != signum:
992 print("sigwait() received %s, not %s" % (received, signum),
993 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200994 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200995 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200996 # unblock the signal, which should have been cleared by sigwait()
997 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
998 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200999
Victor Stinnerb3e72192011-05-08 01:46:11 +02001000 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
1001 'need signal.pthread_sigmask()')
1002 def test_pthread_sigmask_arguments(self):
1003 self.assertRaises(TypeError, signal.pthread_sigmask)
1004 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
1005 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
1006 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
Antoine Pitrou9d3627e2018-05-04 13:00:50 +02001007 with self.assertRaises(ValueError):
1008 signal.pthread_sigmask(signal.SIG_BLOCK, [signal.NSIG])
Serhiy Storchakad54cfb12018-05-08 07:48:50 +03001009 with self.assertRaises(ValueError):
1010 signal.pthread_sigmask(signal.SIG_BLOCK, [0])
1011 with self.assertRaises(ValueError):
1012 signal.pthread_sigmask(signal.SIG_BLOCK, [1<<1000])
Antoine Pitrou9d3627e2018-05-04 13:00:50 +02001013
1014 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
1015 'need signal.pthread_sigmask()')
1016 def test_pthread_sigmask_valid_signals(self):
1017 s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals())
1018 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, s)
1019 # Get current blocked set
1020 s = signal.pthread_sigmask(signal.SIG_UNBLOCK, signal.valid_signals())
1021 self.assertLessEqual(s, signal.valid_signals())
Victor Stinnerb3e72192011-05-08 01:46:11 +02001022
1023 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
1024 'need signal.pthread_sigmask()')
1025 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001026 code = """if 1:
1027 import signal
1028 import os; import threading
1029
1030 def handler(signum, frame):
1031 1/0
1032
1033 def kill(signum):
1034 os.kill(os.getpid(), signum)
1035
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001036 def check_mask(mask):
1037 for sig in mask:
1038 assert isinstance(sig, signal.Signals), repr(sig)
1039
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001040 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001041 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
1042 check_mask(sigmask)
1043 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001044
Victor Stinnerb3e72192011-05-08 01:46:11 +02001045 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +02001046
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001047 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001048 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +02001049
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001050 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +02001051 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001052 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001053 try:
1054 kill(signum)
1055 except ZeroDivisionError:
1056 pass
1057 else:
1058 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001059
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001060 # Block and then raise SIGUSR1. The signal is blocked: the signal
1061 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001062 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
1063 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001064 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +02001065
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001066 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001067 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001068 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +02001069 if signum not in blocked:
1070 raise Exception("%s not in %s" % (signum, blocked))
1071 if old_mask ^ blocked != {signum}:
1072 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +02001073
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001074 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001075 try:
R David Murrayfc069992013-12-13 20:52:19 -05001076 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001077 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001078 except ZeroDivisionError:
1079 pass
1080 else:
1081 raise Exception("ZeroDivisionError not raised")
1082 try:
1083 kill(signum)
1084 except ZeroDivisionError:
1085 pass
1086 else:
1087 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001088
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001089 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001090 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +02001091 if signum in unblocked:
1092 raise Exception("%s in %s" % (signum, unblocked))
1093 if blocked ^ unblocked != {signum}:
1094 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
1095 if old_mask != unblocked:
1096 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001097 """
1098 assert_python_ok('-c', code)
1099
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001100 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
1101 'need signal.pthread_kill()')
1102 def test_pthread_kill_main_thread(self):
1103 # Test that a signal can be sent to the main thread with pthread_kill()
1104 # before any other thread has been created (see issue #12392).
1105 code = """if True:
1106 import threading
1107 import signal
1108 import sys
1109
1110 def handler(signum, frame):
1111 sys.exit(3)
1112
1113 signal.signal(signal.SIGUSR1, handler)
1114 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1115 sys.exit(2)
1116 """
1117
1118 with spawn_python('-c', code) as process:
1119 stdout, stderr = process.communicate()
1120 exitcode = process.wait()
1121 if exitcode != 3:
1122 raise Exception("Child error (exit code %s): %s" %
1123 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001124
1125
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001126class StressTest(unittest.TestCase):
1127 """
1128 Stress signal delivery, especially when a signal arrives in
1129 the middle of recomputing the signal state or executing
1130 previously tripped signal handlers.
1131 """
1132
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001133 def setsig(self, signum, handler):
1134 old_handler = signal.signal(signum, handler)
1135 self.addCleanup(signal.signal, signum, old_handler)
1136
1137 def measure_itimer_resolution(self):
1138 N = 20
1139 times = []
1140
1141 def handler(signum=None, frame=None):
1142 if len(times) < N:
1143 times.append(time.perf_counter())
1144 # 1 µs is the smallest possible timer interval,
1145 # we want to measure what the concrete duration
1146 # will be on this platform
1147 signal.setitimer(signal.ITIMER_REAL, 1e-6)
1148
1149 self.addCleanup(signal.setitimer, signal.ITIMER_REAL, 0)
1150 self.setsig(signal.SIGALRM, handler)
1151 handler()
1152 while len(times) < N:
1153 time.sleep(1e-3)
1154
1155 durations = [times[i+1] - times[i] for i in range(len(times) - 1)]
1156 med = statistics.median(durations)
1157 if support.verbose:
1158 print("detected median itimer() resolution: %.6f s." % (med,))
1159 return med
1160
1161 def decide_itimer_count(self):
1162 # Some systems have poor setitimer() resolution (for example
1163 # measured around 20 ms. on FreeBSD 9), so decide on a reasonable
1164 # number of sequential timers based on that.
1165 reso = self.measure_itimer_resolution()
1166 if reso <= 1e-4:
1167 return 10000
1168 elif reso <= 1e-2:
1169 return 100
1170 else:
1171 self.skipTest("detected itimer resolution (%.3f s.) too high "
1172 "(> 10 ms.) on this platform (or system too busy)"
1173 % (reso,))
1174
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001175 @unittest.skipUnless(hasattr(signal, "setitimer"),
1176 "test needs setitimer()")
1177 def test_stress_delivery_dependent(self):
1178 """
1179 This test uses dependent signal handlers.
1180 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001181 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001182 sigs = []
1183
1184 def first_handler(signum, frame):
1185 # 1e-6 is the minimum non-zero value for `setitimer()`.
1186 # Choose a random delay so as to improve chances of
1187 # triggering a race condition. Ideally the signal is received
1188 # when inside critical signal-handling routines such as
1189 # Py_MakePendingCalls().
1190 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1191
1192 def second_handler(signum=None, frame=None):
1193 sigs.append(signum)
1194
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001195 # Here on Linux, SIGPROF > SIGALRM > SIGUSR1. By using both
1196 # ascending and descending sequences (SIGUSR1 then SIGALRM,
1197 # SIGPROF then SIGALRM), we maximize chances of hitting a bug.
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001198 self.setsig(signal.SIGPROF, first_handler)
1199 self.setsig(signal.SIGUSR1, first_handler)
1200 self.setsig(signal.SIGALRM, second_handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001201
1202 expected_sigs = 0
Victor Stinner0d63bac2019-12-11 11:30:03 +01001203 deadline = time.monotonic() + support.SHORT_TIMEOUT
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001204
1205 while expected_sigs < N:
1206 os.kill(os.getpid(), signal.SIGPROF)
1207 expected_sigs += 1
1208 # Wait for handlers to run to avoid signal coalescing
Victor Stinner2cf4c202018-12-17 09:36:36 +01001209 while len(sigs) < expected_sigs and time.monotonic() < deadline:
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001210 time.sleep(1e-5)
1211
1212 os.kill(os.getpid(), signal.SIGUSR1)
1213 expected_sigs += 1
Victor Stinner2cf4c202018-12-17 09:36:36 +01001214 while len(sigs) < expected_sigs and time.monotonic() < deadline:
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001215 time.sleep(1e-5)
1216
1217 # All ITIMER_REAL signals should have been delivered to the
1218 # Python handler
1219 self.assertEqual(len(sigs), N, "Some signals were lost")
1220
1221 @unittest.skipUnless(hasattr(signal, "setitimer"),
1222 "test needs setitimer()")
1223 def test_stress_delivery_simultaneous(self):
1224 """
1225 This test uses simultaneous signal handlers.
1226 """
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001227 N = self.decide_itimer_count()
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001228 sigs = []
1229
1230 def handler(signum, frame):
1231 sigs.append(signum)
1232
Antoine Pitrouf7d090c2017-06-29 16:40:14 +02001233 self.setsig(signal.SIGUSR1, handler)
1234 self.setsig(signal.SIGALRM, handler) # for ITIMER_REAL
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001235
1236 expected_sigs = 0
Victor Stinner0d63bac2019-12-11 11:30:03 +01001237 deadline = time.monotonic() + support.SHORT_TIMEOUT
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001238
1239 while expected_sigs < N:
1240 # Hopefully the SIGALRM will be received somewhere during
1241 # initial processing of SIGUSR1.
1242 signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5)
1243 os.kill(os.getpid(), signal.SIGUSR1)
1244
1245 expected_sigs += 2
1246 # Wait for handlers to run to avoid signal coalescing
Victor Stinner2cf4c202018-12-17 09:36:36 +01001247 while len(sigs) < expected_sigs and time.monotonic() < deadline:
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001248 time.sleep(1e-5)
1249
1250 # All ITIMER_REAL signals should have been delivered to the
1251 # Python handler
1252 self.assertEqual(len(sigs), N, "Some signals were lost")
1253
Vladimir Matveevc24c6c22019-01-08 01:58:25 -08001254class RaiseSignalTest(unittest.TestCase):
1255
1256 def test_sigint(self):
Gregory P. Smith38f11cc2019-02-16 12:57:40 -08001257 with self.assertRaises(KeyboardInterrupt):
Vladimir Matveevc24c6c22019-01-08 01:58:25 -08001258 signal.raise_signal(signal.SIGINT)
Vladimir Matveevc24c6c22019-01-08 01:58:25 -08001259
1260 @unittest.skipIf(sys.platform != "win32", "Windows specific test")
1261 def test_invalid_argument(self):
1262 try:
1263 SIGHUP = 1 # not supported on win32
1264 signal.raise_signal(SIGHUP)
1265 self.fail("OSError (Invalid argument) expected")
1266 except OSError as e:
1267 if e.errno == errno.EINVAL:
1268 pass
1269 else:
1270 raise
1271
1272 def test_handler(self):
1273 is_ok = False
1274 def handler(a, b):
1275 nonlocal is_ok
1276 is_ok = True
1277 old_signal = signal.signal(signal.SIGINT, handler)
1278 self.addCleanup(signal.signal, signal.SIGINT, old_signal)
1279
1280 signal.raise_signal(signal.SIGINT)
1281 self.assertTrue(is_ok)
1282
Antoine Pitrouc08177a2017-06-28 23:29:29 +02001283
Benjamin Peterson74834512019-11-19 20:39:14 -08001284class PidfdSignalTest(unittest.TestCase):
1285
1286 @unittest.skipUnless(
1287 hasattr(signal, "pidfd_send_signal"),
1288 "pidfd support not built in",
1289 )
1290 def test_pidfd_send_signal(self):
1291 with self.assertRaises(OSError) as cm:
1292 signal.pidfd_send_signal(0, signal.SIGINT)
1293 if cm.exception.errno == errno.ENOSYS:
1294 self.skipTest("kernel does not support pidfds")
Pablo Galindo8f0703f2019-12-29 21:35:54 +00001295 elif cm.exception.errno == errno.EPERM:
1296 self.skipTest("Not enough privileges to use pidfs")
Benjamin Peterson74834512019-11-19 20:39:14 -08001297 self.assertEqual(cm.exception.errno, errno.EBADF)
1298 my_pidfd = os.open(f'/proc/{os.getpid()}', os.O_DIRECTORY)
1299 self.addCleanup(os.close, my_pidfd)
damani4238c878b2020-01-30 11:26:22 +01001300 with self.assertRaisesRegex(TypeError, "^siginfo must be None$"):
Benjamin Peterson74834512019-11-19 20:39:14 -08001301 signal.pidfd_send_signal(my_pidfd, signal.SIGINT, object(), 0)
1302 with self.assertRaises(KeyboardInterrupt):
1303 signal.pidfd_send_signal(my_pidfd, signal.SIGINT)
1304
Zachary Ware38c707e2015-04-13 15:00:43 -05001305def tearDownModule():
1306 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001307
1308if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001309 unittest.main()