blob: 8a404ef7a92ce3bed26547ac5a70b0fae776c929 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002from test import support
Raymond Hettinger722d8c32009-06-18 22:21:03 +00003from contextlib import closing
Christian Heimes4fbc72b2008-03-22 00:47:35 +00004import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00005import signal
Victor Stinner11517102014-07-29 23:31:34 +02006import socket
Victor Stinnerd49b1f12011-05-08 02:03:15 +02007import struct
Christian Heimes4fbc72b2008-03-22 00:47:35 +00008import subprocess
Christian Heimesc06950e2008-02-28 21:17:00 +00009import sys, os, time, errno
Berker Peksagce643912015-05-06 06:33:17 +030010from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020011try:
12 import threading
13except ImportError:
14 threading = None
Victor Stinner56e8c292014-07-21 12:30:22 +020015try:
16 import _testcapi
17except ImportError:
18 _testcapi = None
Christian Heimesc06950e2008-02-28 21:17:00 +000019
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000020
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020021class GenericTests(unittest.TestCase):
22
Stefan Krah63c4b242014-04-15 22:40:06 +020023 @unittest.skipIf(threading is None, "test needs threading module")
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020024 def test_enums(self):
25 for name in dir(signal):
26 sig = getattr(signal, name)
27 if name in {'SIG_DFL', 'SIG_IGN'}:
28 self.assertIsInstance(sig, signal.Handlers)
29 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
30 self.assertIsInstance(sig, signal.Sigmasks)
31 elif name.startswith('SIG') and not name.startswith('SIG_'):
32 self.assertIsInstance(sig, signal.Signals)
33 elif name.startswith('CTRL_'):
34 self.assertIsInstance(sig, signal.Signals)
35 self.assertEqual(sys.platform, "win32")
36
37
Brian Curtin3f004b12010-08-06 19:34:52 +000038@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +020039class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +000040 def trivial_signal_handler(self, *args):
41 pass
42
Thomas Woutersed03b412007-08-28 21:37:11 +000043 def test_out_of_range_signal_number_raises_error(self):
44 self.assertRaises(ValueError, signal.getsignal, 4242)
45
Thomas Woutersed03b412007-08-28 21:37:11 +000046 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +000047 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +000048
49 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
Victor Stinner32eb8402016-03-15 11:12:35 +010061 # Issue 3864, unknown if this affects earlier versions of freebsd also
62 @unittest.skipIf(sys.platform=='freebsd6',
63 'inter process signals not reliable (do not mix well with threading) '
64 'on freebsd6')
65 def test_interprocess_signal(self):
66 dirname = os.path.dirname(__file__)
67 script = os.path.join(dirname, 'signalinterproctester.py')
68 assert_python_ok(script)
69
Christian Heimes4fbc72b2008-03-22 00:47:35 +000070
Brian Curtin3f004b12010-08-06 19:34:52 +000071@unittest.skipUnless(sys.platform == "win32", "Windows specific")
72class WindowsSignalTests(unittest.TestCase):
73 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +000074 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +000075 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +100076 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +000077 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
78 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
79 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +100080 # Set and then reset a handler for signals that work on windows.
81 # Issue #18396, only for signals without a C-level handler.
82 if signal.getsignal(sig) is not None:
83 signal.signal(sig, signal.signal(sig, handler))
84 checked.add(sig)
85 # Issue #18396: Ensure the above loop at least tested *something*
86 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +000087
88 with self.assertRaises(ValueError):
89 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +000090
91 with self.assertRaises(ValueError):
92 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +000093
94
Benjamin Petersonc68a4a02013-01-18 00:10:24 -050095class WakeupFDTests(unittest.TestCase):
96
97 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +020098 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +020099 self.assertRaises((ValueError, OSError),
100 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500101
Victor Stinner11517102014-07-29 23:31:34 +0200102 def test_invalid_socket(self):
103 sock = socket.socket()
104 fd = sock.fileno()
105 sock.close()
106 self.assertRaises((ValueError, OSError),
107 signal.set_wakeup_fd, fd)
108
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200109 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200110 r1, w1 = os.pipe()
111 self.addCleanup(os.close, r1)
112 self.addCleanup(os.close, w1)
113 r2, w2 = os.pipe()
114 self.addCleanup(os.close, r2)
115 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200116
Victor Stinner7cea44d2014-08-27 14:02:36 +0200117 if hasattr(os, 'set_blocking'):
118 os.set_blocking(w1, False)
119 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200120
Victor Stinner1d8948e2014-07-24 22:51:05 +0200121 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200122 self.assertEqual(signal.set_wakeup_fd(w2), w1)
123 self.assertEqual(signal.set_wakeup_fd(-1), w2)
124 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200125
Victor Stinner11517102014-07-29 23:31:34 +0200126 def test_set_wakeup_fd_socket_result(self):
127 sock1 = socket.socket()
128 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200129 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200130 fd1 = sock1.fileno()
131
132 sock2 = socket.socket()
133 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200134 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200135 fd2 = sock2.fileno()
136
137 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200138 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
139 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
140 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200141
Victor Stinner38227602014-08-27 12:59:44 +0200142 # On Windows, files are always blocking and Windows does not provide a
143 # function to test if a socket is in non-blocking mode.
144 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
145 def test_set_wakeup_fd_blocking(self):
146 rfd, wfd = os.pipe()
147 self.addCleanup(os.close, rfd)
148 self.addCleanup(os.close, wfd)
149
150 # fd must be non-blocking
151 os.set_blocking(wfd, True)
152 with self.assertRaises(ValueError) as cm:
153 signal.set_wakeup_fd(wfd)
154 self.assertEqual(str(cm.exception),
155 "the fd %s must be in non-blocking mode" % wfd)
156
157 # non-blocking is ok
158 os.set_blocking(wfd, False)
159 signal.set_wakeup_fd(wfd)
160 signal.set_wakeup_fd(-1)
161
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500162
Brian Curtin3f004b12010-08-06 19:34:52 +0000163@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000164class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200165 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200166 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200167 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200168 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200169 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200170 import os
171 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200172 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000173
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200174 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200175
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200176 def handler(signum, frame):
177 pass
178
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200179 def check_signum(signals):
180 data = os.read(read, len(signals)+1)
181 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200182 if not {!r}:
183 raised = set(raised)
184 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200185 if raised != signals:
186 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200187
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200188 {}
189
190 signal.signal(signal.SIGALRM, handler)
191 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200192 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200193 signal.set_wakeup_fd(write)
194
195 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200196 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200197
198 os.close(read)
199 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200200 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200201
202 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200203
Victor Stinner56e8c292014-07-21 12:30:22 +0200204 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200205 def test_wakeup_write_error(self):
206 # Issue #16105: write() errors in the C signal handler should not
207 # pass silently.
208 # Use a subprocess to have only one thread.
209 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200210 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200211 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200212 import os
213 import signal
214 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200215 from test.support import captured_stderr
216
217 def handler(signum, frame):
218 1/0
219
220 signal.signal(signal.SIGALRM, handler)
221 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200222 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200223
224 # Set wakeup_fd a read-only file descriptor to trigger the error
225 signal.set_wakeup_fd(r)
226 try:
227 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200228 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200229 except ZeroDivisionError:
230 # An ignored exception should have been printed out on stderr
231 err = err.getvalue()
232 if ('Exception ignored when trying to write to the signal wakeup fd'
233 not in err):
234 raise AssertionError(err)
235 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
236 raise AssertionError(err)
237 else:
238 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200239
240 os.close(r)
241 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200242 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200243 r, w = os.pipe()
244 try:
245 os.write(r, b'x')
246 except OSError:
247 pass
248 else:
249 self.skipTest("OS doesn't report write() error on the read end of a pipe")
250 finally:
251 os.close(r)
252 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200253
254 assert_python_ok('-c', code)
255
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000256 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200257 self.check_wakeup("""def test():
258 import select
259 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000260
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200261 TIMEOUT_FULL = 10
262 TIMEOUT_HALF = 5
263
Victor Stinner749a6a82015-03-30 22:09:14 +0200264 class InterruptSelect(Exception):
265 pass
266
267 def handler(signum, frame):
268 raise InterruptSelect
269 signal.signal(signal.SIGALRM, handler)
270
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200271 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100272
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200273 # We attempt to get a signal during the sleep,
274 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100275 try:
276 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200277 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100278 pass
279 else:
280 raise Exception("select() was not interrupted")
281
282 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200283 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100284 after_time = time.monotonic()
285 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200286 if dt >= TIMEOUT_HALF:
287 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200288 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000289
290 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200291 self.check_wakeup("""def test():
292 import select
293 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000294
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200295 TIMEOUT_FULL = 10
296 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000297
Victor Stinner749a6a82015-03-30 22:09:14 +0200298 class InterruptSelect(Exception):
299 pass
300
301 def handler(signum, frame):
302 raise InterruptSelect
303 signal.signal(signal.SIGALRM, handler)
304
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200305 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100306 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200307 # We attempt to get a signal during the select call
308 try:
309 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200310 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200311 pass
312 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200313 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100314 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200315 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200316 if dt >= TIMEOUT_HALF:
317 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200318 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200319
320 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200321 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200322 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200323 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200324 _testcapi.raise_signal(signal.SIGUSR1)
325 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200326 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000327
Victor Stinnerc13ef662011-05-25 02:35:58 +0200328 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
329 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200330 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200331 self.check_wakeup("""def test():
332 signum1 = signal.SIGUSR1
333 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200334
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200335 signal.signal(signum1, handler)
336 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200337
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200338 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200339 _testcapi.raise_signal(signum1)
340 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200341 # Unblocking the 2 signals calls the C signal handler twice
342 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200343 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200344
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000345
Victor Stinner11517102014-07-29 23:31:34 +0200346@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
347class WakeupSocketSignalTests(unittest.TestCase):
348
349 @unittest.skipIf(_testcapi is None, 'need _testcapi')
350 def test_socket(self):
351 # use a subprocess to have only one thread
352 code = """if 1:
353 import signal
354 import socket
355 import struct
356 import _testcapi
357
358 signum = signal.SIGINT
359 signals = (signum,)
360
361 def handler(signum, frame):
362 pass
363
364 signal.signal(signum, handler)
365
366 read, write = socket.socketpair()
367 read.setblocking(False)
368 write.setblocking(False)
369 signal.set_wakeup_fd(write.fileno())
370
371 _testcapi.raise_signal(signum)
372
373 data = read.recv(1)
374 if not data:
375 raise Exception("no signum written")
376 raised = struct.unpack('B', data)
377 if raised != signals:
378 raise Exception("%r != %r" % (raised, signals))
379
380 read.close()
381 write.close()
382 """
383
384 assert_python_ok('-c', code)
385
386 @unittest.skipIf(_testcapi is None, 'need _testcapi')
387 def test_send_error(self):
388 # Use a subprocess to have only one thread.
389 if os.name == 'nt':
390 action = 'send'
391 else:
392 action = 'write'
393 code = """if 1:
394 import errno
395 import signal
396 import socket
397 import sys
398 import time
399 import _testcapi
400 from test.support import captured_stderr
401
402 signum = signal.SIGINT
403
404 def handler(signum, frame):
405 pass
406
407 signal.signal(signum, handler)
408
409 read, write = socket.socketpair()
410 read.setblocking(False)
411 write.setblocking(False)
412
413 signal.set_wakeup_fd(write.fileno())
414
415 # Close sockets: send() will fail
416 read.close()
417 write.close()
418
419 with captured_stderr() as err:
420 _testcapi.raise_signal(signum)
421
422 err = err.getvalue()
423 if ('Exception ignored when trying to {action} to the signal wakeup fd'
424 not in err):
425 raise AssertionError(err)
426 """.format(action=action)
427 assert_python_ok('-c', code)
428
429
Brian Curtin3f004b12010-08-06 19:34:52 +0000430@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000431class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000432
Victor Stinnerd6284962011-06-20 23:28:09 +0200433 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000434 """Perform a read during which a signal will arrive. Return True if the
435 read is interrupted by the signal and raises an exception. Return False
436 if it returns normally.
437 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200438 # use a subprocess to have only one thread, to have a timeout on the
439 # blocking read and to not touch signal handling in this process
440 code = """if 1:
441 import errno
442 import os
443 import signal
444 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000445
Victor Stinnerd6284962011-06-20 23:28:09 +0200446 interrupt = %r
447 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000448
Victor Stinnerd6284962011-06-20 23:28:09 +0200449 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000450 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200451
452 signal.signal(signal.SIGALRM, handler)
453 if interrupt is not None:
454 signal.siginterrupt(signal.SIGALRM, interrupt)
455
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200456 print("ready")
457 sys.stdout.flush()
458
Victor Stinnerd6284962011-06-20 23:28:09 +0200459 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200460 try:
461 for loop in range(2):
462 # send a SIGALRM in a second (during the read)
463 signal.alarm(1)
464 try:
465 # blocking call: read from a pipe without data
466 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000467 except ZeroDivisionError:
468 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200469 else:
470 sys.exit(2)
471 sys.exit(3)
472 finally:
473 os.close(r)
474 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200475 """ % (interrupt,)
476 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000477 try:
Victor Stinner45273652011-06-22 22:15:51 +0200478 # wait until the child process is loaded and has started
479 first_line = process.stdout.readline()
480
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200481 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200482 except subprocess.TimeoutExpired:
483 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000484 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200485 else:
Victor Stinner45273652011-06-22 22:15:51 +0200486 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200487 exitcode = process.wait()
488 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200489 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200490 % (exitcode, stdout))
491 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000492
493 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200494 # If a signal handler is installed and siginterrupt is not called
495 # at all, when that signal arrives, it interrupts a syscall that's in
496 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200497 interrupted = self.readpipe_interrupted(None)
498 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000499
500 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200501 # If a signal handler is installed and siginterrupt is called with
502 # a true value for the second argument, when that signal arrives, it
503 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200504 interrupted = self.readpipe_interrupted(True)
505 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000506
507 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200508 # If a signal handler is installed and siginterrupt is called with
509 # a false value for the second argument, when that signal arrives, it
510 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200511 interrupted = self.readpipe_interrupted(False)
512 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000513
514
Brian Curtin3f004b12010-08-06 19:34:52 +0000515@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000516class ItimerTest(unittest.TestCase):
517 def setUp(self):
518 self.hndl_called = False
519 self.hndl_count = 0
520 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000521 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000522
523 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000524 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000525 if self.itimer is not None: # test_itimer_exc doesn't change this attr
526 # just ensure that itimer is stopped
527 signal.setitimer(self.itimer, 0)
528
529 def sig_alrm(self, *args):
530 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000531
532 def sig_vtalrm(self, *args):
533 self.hndl_called = True
534
535 if self.hndl_count > 3:
536 # it shouldn't be here, because it should have been disabled.
537 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
538 "timer.")
539 elif self.hndl_count == 3:
540 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
541 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000542
543 self.hndl_count += 1
544
Martin v. Löwis823725e2008-03-24 13:39:54 +0000545 def sig_prof(self, *args):
546 self.hndl_called = True
547 signal.setitimer(signal.ITIMER_PROF, 0)
548
Martin v. Löwis823725e2008-03-24 13:39:54 +0000549 def test_itimer_exc(self):
550 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
551 # defines it ?
552 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000553 # Negative times are treated as zero on some platforms.
554 if 0:
555 self.assertRaises(signal.ItimerError,
556 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000557
558 def test_itimer_real(self):
559 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000560 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000561 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000562 self.assertEqual(self.hndl_called, True)
563
R. David Murray44546f82010-04-21 01:59:28 +0000564 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000565 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
566 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000567 def test_itimer_virtual(self):
568 self.itimer = signal.ITIMER_VIRTUAL
569 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
570 signal.setitimer(self.itimer, 0.3, 0.2)
571
Victor Stinner79d68f92015-03-19 21:54:09 +0100572 start_time = time.monotonic()
573 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000574 # use up some virtual time by doing real work
575 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000576 if signal.getitimer(self.itimer) == (0.0, 0.0):
577 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000578 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000579 self.skipTest("timeout: likely cause: machine too slow or load too "
580 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000581
582 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000583 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000584 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000585 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000586
R. David Murray44546f82010-04-21 01:59:28 +0000587 # Issue 3864, unknown if this affects earlier versions of freebsd also
588 @unittest.skipIf(sys.platform=='freebsd6',
589 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000590 def test_itimer_prof(self):
591 self.itimer = signal.ITIMER_PROF
592 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000593 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000594
Victor Stinner79d68f92015-03-19 21:54:09 +0100595 start_time = time.monotonic()
596 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000597 # do some work
598 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000599 if signal.getitimer(self.itimer) == (0.0, 0.0):
600 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000601 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000602 self.skipTest("timeout: likely cause: machine too slow or load too "
603 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000604
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000605 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000606 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000607 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000608 self.assertEqual(self.hndl_called, True)
609
Victor Stinnera9293352011-04-30 15:21:58 +0200610
Victor Stinner35b300c2011-05-04 13:20:35 +0200611class PendingSignalsTests(unittest.TestCase):
612 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200613 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
614 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200615 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200616 @unittest.skipUnless(hasattr(signal, 'sigpending'),
617 'need signal.sigpending()')
618 def test_sigpending_empty(self):
619 self.assertEqual(signal.sigpending(), set())
620
621 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
622 'need signal.pthread_sigmask()')
623 @unittest.skipUnless(hasattr(signal, 'sigpending'),
624 'need signal.sigpending()')
625 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200626 code = """if 1:
627 import os
628 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200629
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200630 def handler(signum, frame):
631 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200632
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200633 signum = signal.SIGUSR1
634 signal.signal(signum, handler)
635
636 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
637 os.kill(os.getpid(), signum)
638 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200639 for sig in pending:
640 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200641 if pending != {signum}:
642 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200643 try:
644 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
645 except ZeroDivisionError:
646 pass
647 else:
648 raise Exception("ZeroDivisionError not raised")
649 """
650 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200651
652 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
653 'need signal.pthread_kill()')
654 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200655 code = """if 1:
656 import signal
657 import threading
658 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200659
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200660 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200661
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200662 def handler(signum, frame):
663 1/0
664
665 signal.signal(signum, handler)
666
667 if sys.platform == 'freebsd6':
668 # Issue #12392 and #12469: send a signal to the main thread
669 # doesn't work before the creation of the first thread on
670 # FreeBSD 6
671 def noop():
672 pass
673 thread = threading.Thread(target=noop)
674 thread.start()
675 thread.join()
676
677 tid = threading.get_ident()
678 try:
679 signal.pthread_kill(tid, signum)
680 except ZeroDivisionError:
681 pass
682 else:
683 raise Exception("ZeroDivisionError not raised")
684 """
685 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200686
Victor Stinner7f294d12011-06-10 14:02:10 +0200687 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
688 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200689 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200690 """
691 test: body of the "def test(signum):" function.
692 blocked: number of the blocked signal
693 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200694 code = '''if 1:
695 import signal
696 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200697 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200698
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200699 def handler(signum, frame):
700 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200701
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200702 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200703
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200704 blocked = %s
705 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200706
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200707 # child: block and wait the signal
708 try:
709 signal.signal(signum, handler)
710 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200711
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200712 # Do the tests
713 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200714
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200715 # The handler must not be called on unblock
716 try:
717 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
718 except ZeroDivisionError:
719 print("the signal handler has been called",
720 file=sys.stderr)
721 sys.exit(1)
722 except BaseException as err:
723 print("error: {}".format(err), file=sys.stderr)
724 sys.stderr.flush()
725 sys.exit(1)
726 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200727
Ross Lagerwallbc808222011-06-25 12:13:40 +0200728 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200729 # process might have several threads running, use a subprocess to have
730 # a single thread.
731 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200732
Victor Stinnerb3e72192011-05-08 01:46:11 +0200733 @unittest.skipUnless(hasattr(signal, 'sigwait'),
734 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200735 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200736 self.wait_helper(signal.SIGALRM, '''
737 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200738 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200739 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200740 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200741 if received != signum:
742 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200743 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200744
745 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
746 'need signal.sigwaitinfo()')
747 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200748 self.wait_helper(signal.SIGALRM, '''
749 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200750 signal.alarm(1)
751 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200752 if info.si_signo != signum:
753 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200754 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200755
756 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
757 'need signal.sigtimedwait()')
758 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200759 self.wait_helper(signal.SIGALRM, '''
760 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200761 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100762 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200763 if info.si_signo != signum:
764 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200765 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200766
Ross Lagerwallbc808222011-06-25 12:13:40 +0200767 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
768 'need signal.sigtimedwait()')
769 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200770 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200771 self.wait_helper(signal.SIGALRM, '''
772 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200773 import os
774 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100775 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200776 if info.si_signo != signum:
777 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200778 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200779
780 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
781 'need signal.sigtimedwait()')
782 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200783 self.wait_helper(signal.SIGALRM, '''
784 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100785 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200786 if received is not None:
787 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200788 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200789
790 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
791 'need signal.sigtimedwait()')
792 def test_sigtimedwait_negative_timeout(self):
793 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100794 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200795
Ross Lagerwallbc808222011-06-25 12:13:40 +0200796 @unittest.skipUnless(hasattr(signal, 'sigwait'),
797 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200798 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
799 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200800 @unittest.skipIf(threading is None, "test needs threading module")
801 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200802 # Check that calling sigwait() from a thread doesn't suspend the whole
803 # process. A new interpreter is spawned to avoid problems when mixing
804 # threads and fork(): only async-safe functions are allowed between
805 # fork() and exec().
806 assert_python_ok("-c", """if True:
807 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200808
Victor Stinner415007e2011-06-13 16:19:06 +0200809 # the default handler terminates the process
810 signum = signal.SIGUSR1
811
812 def kill_later():
813 # wait until the main thread is waiting in sigwait()
814 time.sleep(1)
815 os.kill(os.getpid(), signum)
816
817 # the signal must be blocked by all the threads
818 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
819 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200820 killer.start()
821 received = signal.sigwait([signum])
822 if received != signum:
823 print("sigwait() received %s, not %s" % (received, signum),
824 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200825 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200826 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200827 # unblock the signal, which should have been cleared by sigwait()
828 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
829 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200830
Victor Stinnerb3e72192011-05-08 01:46:11 +0200831 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
832 'need signal.pthread_sigmask()')
833 def test_pthread_sigmask_arguments(self):
834 self.assertRaises(TypeError, signal.pthread_sigmask)
835 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
836 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
837 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
838
839 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
840 'need signal.pthread_sigmask()')
841 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200842 code = """if 1:
843 import signal
844 import os; import threading
845
846 def handler(signum, frame):
847 1/0
848
849 def kill(signum):
850 os.kill(os.getpid(), signum)
851
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200852 def check_mask(mask):
853 for sig in mask:
854 assert isinstance(sig, signal.Signals), repr(sig)
855
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200856 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200857 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
858 check_mask(sigmask)
859 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200860
Victor Stinnerb3e72192011-05-08 01:46:11 +0200861 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200862
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200863 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200864 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200865
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200866 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200867 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200868 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200869 try:
870 kill(signum)
871 except ZeroDivisionError:
872 pass
873 else:
874 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200875
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200876 # Block and then raise SIGUSR1. The signal is blocked: the signal
877 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200878 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
879 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200880 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200881
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200882 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200883 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200884 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +0200885 if signum not in blocked:
886 raise Exception("%s not in %s" % (signum, blocked))
887 if old_mask ^ blocked != {signum}:
888 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200889
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200890 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200891 try:
R David Murrayfc069992013-12-13 20:52:19 -0500892 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200893 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200894 except ZeroDivisionError:
895 pass
896 else:
897 raise Exception("ZeroDivisionError not raised")
898 try:
899 kill(signum)
900 except ZeroDivisionError:
901 pass
902 else:
903 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200904
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200905 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200906 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200907 if signum in unblocked:
908 raise Exception("%s in %s" % (signum, unblocked))
909 if blocked ^ unblocked != {signum}:
910 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
911 if old_mask != unblocked:
912 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200913 """
914 assert_python_ok('-c', code)
915
916 @unittest.skipIf(sys.platform == 'freebsd6',
917 "issue #12392: send a signal to the main thread doesn't work "
918 "before the creation of the first thread on FreeBSD 6")
919 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
920 'need signal.pthread_kill()')
921 def test_pthread_kill_main_thread(self):
922 # Test that a signal can be sent to the main thread with pthread_kill()
923 # before any other thread has been created (see issue #12392).
924 code = """if True:
925 import threading
926 import signal
927 import sys
928
929 def handler(signum, frame):
930 sys.exit(3)
931
932 signal.signal(signal.SIGUSR1, handler)
933 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
934 sys.exit(2)
935 """
936
937 with spawn_python('-c', code) as process:
938 stdout, stderr = process.communicate()
939 exitcode = process.wait()
940 if exitcode != 3:
941 raise Exception("Child error (exit code %s): %s" %
942 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200943
944
Zachary Ware38c707e2015-04-13 15:00:43 -0500945def tearDownModule():
946 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000947
948if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500949 unittest.main()