blob: 1b80ff0963b8d7b02e300e03ef54ee34d99c7b71 [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
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02004import enum
Christian Heimescc47b052008-03-25 14:56:36 +00005import gc
Christian Heimes4fbc72b2008-03-22 00:47:35 +00006import pickle
7import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00008import signal
Victor Stinner11517102014-07-29 23:31:34 +02009import socket
Victor Stinnerd49b1f12011-05-08 02:03:15 +020010import struct
Christian Heimes4fbc72b2008-03-22 00:47:35 +000011import subprocess
12import traceback
Christian Heimesc06950e2008-02-28 21:17:00 +000013import sys, os, time, errno
Berker Peksagce643912015-05-06 06:33:17 +030014from test.support.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020015try:
16 import threading
17except ImportError:
18 threading = None
Victor Stinner56e8c292014-07-21 12:30:22 +020019try:
20 import _testcapi
21except ImportError:
22 _testcapi = None
Christian Heimesc06950e2008-02-28 21:17:00 +000023
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000024
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000025class HandlerBCalled(Exception):
26 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000027
Christian Heimes4fbc72b2008-03-22 00:47:35 +000028
29def exit_subprocess():
30 """Use os._exit(0) to exit the current subprocess.
31
32 Otherwise, the test catches the SystemExit and continues executing
33 in parallel with the original test, so you wind up with an
34 exponential number of tests running concurrently.
35 """
36 os._exit(0)
37
38
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000039def ignoring_eintr(__func, *args, **kwargs):
40 try:
41 return __func(*args, **kwargs)
Andrew Svetlov3438fa42012-12-17 23:35:18 +020042 except OSError as e:
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000043 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000044 raise
45 return None
46
47
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020048class GenericTests(unittest.TestCase):
49
Stefan Krah63c4b242014-04-15 22:40:06 +020050 @unittest.skipIf(threading is None, "test needs threading module")
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +020051 def test_enums(self):
52 for name in dir(signal):
53 sig = getattr(signal, name)
54 if name in {'SIG_DFL', 'SIG_IGN'}:
55 self.assertIsInstance(sig, signal.Handlers)
56 elif name in {'SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'}:
57 self.assertIsInstance(sig, signal.Sigmasks)
58 elif name.startswith('SIG') and not name.startswith('SIG_'):
59 self.assertIsInstance(sig, signal.Signals)
60 elif name.startswith('CTRL_'):
61 self.assertIsInstance(sig, signal.Signals)
62 self.assertEqual(sys.platform, "win32")
63
64
Brian Curtin3f004b12010-08-06 19:34:52 +000065@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000066class InterProcessSignalTests(unittest.TestCase):
67 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000068
Christian Heimescc47b052008-03-25 14:56:36 +000069 def setUp(self):
70 self.using_gc = gc.isenabled()
71 gc.disable()
72
73 def tearDown(self):
74 if self.using_gc:
75 gc.enable()
76
Christian Heimes5e696852008-04-09 08:37:03 +000077 def format_frame(self, frame, limit=None):
78 return ''.join(traceback.format_stack(frame, limit=limit))
79
80 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000081 self.a_called = True
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000082
Christian Heimes5e696852008-04-09 08:37:03 +000083 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000084 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000085 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000086
Christian Heimes4fbc72b2008-03-22 00:47:35 +000087 def wait(self, child):
88 """Wait for child to finish, ignoring EINTR."""
89 while True:
90 try:
91 child.wait()
92 return
93 except OSError as e:
94 if e.errno != errno.EINTR:
95 raise
Fred Drake004d5e62000-10-23 17:22:08 +000096
Christian Heimes4fbc72b2008-03-22 00:47:35 +000097 def run_test(self):
98 # Install handlers. This function runs in a sub-process, so we
99 # don't worry about re-setting the default handlers.
100 signal.signal(signal.SIGHUP, self.handlerA)
101 signal.signal(signal.SIGUSR1, self.handlerB)
102 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
103 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +0000104
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000105 # Variables the signals will modify:
106 self.a_called = False
107 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000108
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000109 # Let the sub-processes know who to send signals to.
110 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000111
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000112 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
113 if child:
114 self.wait(child)
115 if not self.a_called:
116 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000117 self.assertTrue(self.a_called)
118 self.assertFalse(self.b_called)
119 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000120
Christian Heimes5e696852008-04-09 08:37:03 +0000121 # Make sure the signal isn't delivered while the previous
122 # Popen object is being destroyed, because __del__ swallows
123 # exceptions.
124 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000125 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000126 child = subprocess.Popen(['kill', '-USR1', str(pid)])
127 # This wait should be interrupted by the signal's exception.
128 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000129 time.sleep(1) # Give the signal time to be delivered.
Andrew Svetlov737fb892012-12-18 21:14:22 +0200130 self.fail('HandlerBCalled exception not raised')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000131 except HandlerBCalled:
132 self.assertTrue(self.b_called)
133 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000134
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000135 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
136 if child:
137 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000138
139 try:
140 signal.alarm(1)
141 # The race condition in pause doesn't matter in this case,
142 # since alarm is going to raise a KeyboardException, which
143 # will skip the call.
144 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000145 # But if another signal arrives before the alarm, pause
146 # may return early.
147 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000148 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200149 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000150 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000151 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000152 traceback.format_exc())
153 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000154 self.fail("pause returned of its own accord, and the signal"
155 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000156
R. David Murray44546f82010-04-21 01:59:28 +0000157 # Issue 3864, unknown if this affects earlier versions of freebsd also
158 @unittest.skipIf(sys.platform=='freebsd6',
159 'inter process signals not reliable (do not mix well with threading) '
160 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000161 def test_main(self):
162 # This function spawns a child process to insulate the main
163 # test-running process from all the signals. It then
164 # communicates with that child process over a pipe and
165 # re-raises information about any exceptions the child
Andrew Svetlov737fb892012-12-18 21:14:22 +0200166 # raises. The real work happens in self.run_test().
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000167 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000168 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
169 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000170 child = os.fork()
171 if child == 0:
172 # In the child process; run the test and report results
173 # through the pipe.
174 try:
175 done_r.close()
176 # Have to close done_w again here because
177 # exit_subprocess() will skip the enclosing with block.
178 with closing(done_w):
179 try:
180 self.run_test()
181 except:
182 pickle.dump(traceback.format_exc(), done_w)
183 else:
184 pickle.dump(None, done_w)
185 except:
186 print('Uh oh, raised from pickle.')
187 traceback.print_exc()
188 finally:
189 exit_subprocess()
190
191 done_w.close()
192 # Block for up to MAX_DURATION seconds for the test to finish.
193 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
194 if done_r in r:
195 tb = pickle.load(done_r)
196 if tb:
197 self.fail(tb)
198 else:
199 os.kill(child, signal.SIGKILL)
200 self.fail('Test deadlocked after %d seconds.' %
201 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000202
203
Brian Curtin3f004b12010-08-06 19:34:52 +0000204@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200205class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000206 def trivial_signal_handler(self, *args):
207 pass
208
Thomas Woutersed03b412007-08-28 21:37:11 +0000209 def test_out_of_range_signal_number_raises_error(self):
210 self.assertRaises(ValueError, signal.getsignal, 4242)
211
Thomas Woutersed03b412007-08-28 21:37:11 +0000212 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000213 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000214
215 def test_setting_signal_handler_to_none_raises_error(self):
216 self.assertRaises(TypeError, signal.signal,
217 signal.SIGUSR1, None)
218
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000219 def test_getsignal(self):
220 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200221 self.assertIsInstance(hup, signal.Handlers)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000222 self.assertEqual(signal.getsignal(signal.SIGHUP),
223 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000224 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000225 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000226
227
Brian Curtin3f004b12010-08-06 19:34:52 +0000228@unittest.skipUnless(sys.platform == "win32", "Windows specific")
229class WindowsSignalTests(unittest.TestCase):
230 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000231 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000232 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000233 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +0000234 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
235 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
236 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000237 # Set and then reset a handler for signals that work on windows.
238 # Issue #18396, only for signals without a C-level handler.
239 if signal.getsignal(sig) is not None:
240 signal.signal(sig, signal.signal(sig, handler))
241 checked.add(sig)
242 # Issue #18396: Ensure the above loop at least tested *something*
243 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +0000244
245 with self.assertRaises(ValueError):
246 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000247
248 with self.assertRaises(ValueError):
249 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000250
251
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500252class WakeupFDTests(unittest.TestCase):
253
254 def test_invalid_fd(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200255 fd = support.make_bad_fd()
Victor Stinnera7d03d92014-07-21 17:17:28 +0200256 self.assertRaises((ValueError, OSError),
257 signal.set_wakeup_fd, fd)
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500258
Victor Stinner11517102014-07-29 23:31:34 +0200259 def test_invalid_socket(self):
260 sock = socket.socket()
261 fd = sock.fileno()
262 sock.close()
263 self.assertRaises((ValueError, OSError),
264 signal.set_wakeup_fd, fd)
265
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200266 def test_set_wakeup_fd_result(self):
Victor Stinner1d8948e2014-07-24 22:51:05 +0200267 r1, w1 = os.pipe()
268 self.addCleanup(os.close, r1)
269 self.addCleanup(os.close, w1)
270 r2, w2 = os.pipe()
271 self.addCleanup(os.close, r2)
272 self.addCleanup(os.close, w2)
Victor Stinnerd18ccd12014-07-24 21:58:53 +0200273
Victor Stinner7cea44d2014-08-27 14:02:36 +0200274 if hasattr(os, 'set_blocking'):
275 os.set_blocking(w1, False)
276 os.set_blocking(w2, False)
Victor Stinner38227602014-08-27 12:59:44 +0200277
Victor Stinner1d8948e2014-07-24 22:51:05 +0200278 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200279 self.assertEqual(signal.set_wakeup_fd(w2), w1)
280 self.assertEqual(signal.set_wakeup_fd(-1), w2)
281 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200282
Victor Stinner11517102014-07-29 23:31:34 +0200283 def test_set_wakeup_fd_socket_result(self):
284 sock1 = socket.socket()
285 self.addCleanup(sock1.close)
Victor Stinner38227602014-08-27 12:59:44 +0200286 sock1.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200287 fd1 = sock1.fileno()
288
289 sock2 = socket.socket()
290 self.addCleanup(sock2.close)
Victor Stinner38227602014-08-27 12:59:44 +0200291 sock2.setblocking(False)
Victor Stinner11517102014-07-29 23:31:34 +0200292 fd2 = sock2.fileno()
293
294 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200295 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
296 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
297 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200298
Victor Stinner38227602014-08-27 12:59:44 +0200299 # On Windows, files are always blocking and Windows does not provide a
300 # function to test if a socket is in non-blocking mode.
301 @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX")
302 def test_set_wakeup_fd_blocking(self):
303 rfd, wfd = os.pipe()
304 self.addCleanup(os.close, rfd)
305 self.addCleanup(os.close, wfd)
306
307 # fd must be non-blocking
308 os.set_blocking(wfd, True)
309 with self.assertRaises(ValueError) as cm:
310 signal.set_wakeup_fd(wfd)
311 self.assertEqual(str(cm.exception),
312 "the fd %s must be in non-blocking mode" % wfd)
313
314 # non-blocking is ok
315 os.set_blocking(wfd, False)
316 signal.set_wakeup_fd(wfd)
317 signal.set_wakeup_fd(-1)
318
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500319
Brian Curtin3f004b12010-08-06 19:34:52 +0000320@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000321class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200322 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200323 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200324 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200325 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200326 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200327 import os
328 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200329 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000330
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200331 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200332
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200333 def handler(signum, frame):
334 pass
335
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200336 def check_signum(signals):
337 data = os.read(read, len(signals)+1)
338 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200339 if not {!r}:
340 raised = set(raised)
341 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200342 if raised != signals:
343 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200344
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200345 {}
346
347 signal.signal(signal.SIGALRM, handler)
348 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200349 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200350 signal.set_wakeup_fd(write)
351
352 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200353 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200354
355 os.close(read)
356 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200357 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200358
359 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200360
Victor Stinner56e8c292014-07-21 12:30:22 +0200361 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200362 def test_wakeup_write_error(self):
363 # Issue #16105: write() errors in the C signal handler should not
364 # pass silently.
365 # Use a subprocess to have only one thread.
366 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200367 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200368 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200369 import os
370 import signal
371 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200372 from test.support import captured_stderr
373
374 def handler(signum, frame):
375 1/0
376
377 signal.signal(signal.SIGALRM, handler)
378 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200379 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200380
381 # Set wakeup_fd a read-only file descriptor to trigger the error
382 signal.set_wakeup_fd(r)
383 try:
384 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200385 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200386 except ZeroDivisionError:
387 # An ignored exception should have been printed out on stderr
388 err = err.getvalue()
389 if ('Exception ignored when trying to write to the signal wakeup fd'
390 not in err):
391 raise AssertionError(err)
392 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
393 raise AssertionError(err)
394 else:
395 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200396
397 os.close(r)
398 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200399 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200400 r, w = os.pipe()
401 try:
402 os.write(r, b'x')
403 except OSError:
404 pass
405 else:
406 self.skipTest("OS doesn't report write() error on the read end of a pipe")
407 finally:
408 os.close(r)
409 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200410
411 assert_python_ok('-c', code)
412
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000413 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200414 self.check_wakeup("""def test():
415 import select
416 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000417
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200418 TIMEOUT_FULL = 10
419 TIMEOUT_HALF = 5
420
Victor Stinner749a6a82015-03-30 22:09:14 +0200421 class InterruptSelect(Exception):
422 pass
423
424 def handler(signum, frame):
425 raise InterruptSelect
426 signal.signal(signal.SIGALRM, handler)
427
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200428 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100429
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200430 # We attempt to get a signal during the sleep,
431 # before select is called
Victor Stinner79d68f92015-03-19 21:54:09 +0100432 try:
433 select.select([], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200434 except InterruptSelect:
Victor Stinner79d68f92015-03-19 21:54:09 +0100435 pass
436 else:
437 raise Exception("select() was not interrupted")
438
439 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200440 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner79d68f92015-03-19 21:54:09 +0100441 after_time = time.monotonic()
442 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200443 if dt >= TIMEOUT_HALF:
444 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200445 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000446
447 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200448 self.check_wakeup("""def test():
449 import select
450 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000451
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200452 TIMEOUT_FULL = 10
453 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000454
Victor Stinner749a6a82015-03-30 22:09:14 +0200455 class InterruptSelect(Exception):
456 pass
457
458 def handler(signum, frame):
459 raise InterruptSelect
460 signal.signal(signal.SIGALRM, handler)
461
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200462 signal.alarm(1)
Victor Stinner79d68f92015-03-19 21:54:09 +0100463 before_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200464 # We attempt to get a signal during the select call
465 try:
466 select.select([read], [], [], TIMEOUT_FULL)
Victor Stinner749a6a82015-03-30 22:09:14 +0200467 except InterruptSelect:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200468 pass
469 else:
Victor Stinner749a6a82015-03-30 22:09:14 +0200470 raise Exception("select() was not interrupted")
Victor Stinner79d68f92015-03-19 21:54:09 +0100471 after_time = time.monotonic()
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200472 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200473 if dt >= TIMEOUT_HALF:
474 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200475 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200476
477 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200478 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200479 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200480 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200481 _testcapi.raise_signal(signal.SIGUSR1)
482 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200483 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000484
Victor Stinnerc13ef662011-05-25 02:35:58 +0200485 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
486 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200487 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200488 self.check_wakeup("""def test():
489 signum1 = signal.SIGUSR1
490 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200491
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200492 signal.signal(signum1, handler)
493 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200494
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200495 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200496 _testcapi.raise_signal(signum1)
497 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200498 # Unblocking the 2 signals calls the C signal handler twice
499 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200500 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200501
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000502
Victor Stinner11517102014-07-29 23:31:34 +0200503@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
504class WakeupSocketSignalTests(unittest.TestCase):
505
506 @unittest.skipIf(_testcapi is None, 'need _testcapi')
507 def test_socket(self):
508 # use a subprocess to have only one thread
509 code = """if 1:
510 import signal
511 import socket
512 import struct
513 import _testcapi
514
515 signum = signal.SIGINT
516 signals = (signum,)
517
518 def handler(signum, frame):
519 pass
520
521 signal.signal(signum, handler)
522
523 read, write = socket.socketpair()
524 read.setblocking(False)
525 write.setblocking(False)
526 signal.set_wakeup_fd(write.fileno())
527
528 _testcapi.raise_signal(signum)
529
530 data = read.recv(1)
531 if not data:
532 raise Exception("no signum written")
533 raised = struct.unpack('B', data)
534 if raised != signals:
535 raise Exception("%r != %r" % (raised, signals))
536
537 read.close()
538 write.close()
539 """
540
541 assert_python_ok('-c', code)
542
543 @unittest.skipIf(_testcapi is None, 'need _testcapi')
544 def test_send_error(self):
545 # Use a subprocess to have only one thread.
546 if os.name == 'nt':
547 action = 'send'
548 else:
549 action = 'write'
550 code = """if 1:
551 import errno
552 import signal
553 import socket
554 import sys
555 import time
556 import _testcapi
557 from test.support import captured_stderr
558
559 signum = signal.SIGINT
560
561 def handler(signum, frame):
562 pass
563
564 signal.signal(signum, handler)
565
566 read, write = socket.socketpair()
567 read.setblocking(False)
568 write.setblocking(False)
569
570 signal.set_wakeup_fd(write.fileno())
571
572 # Close sockets: send() will fail
573 read.close()
574 write.close()
575
576 with captured_stderr() as err:
577 _testcapi.raise_signal(signum)
578
579 err = err.getvalue()
580 if ('Exception ignored when trying to {action} to the signal wakeup fd'
581 not in err):
582 raise AssertionError(err)
583 """.format(action=action)
584 assert_python_ok('-c', code)
585
586
Brian Curtin3f004b12010-08-06 19:34:52 +0000587@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000588class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000589
Victor Stinnerd6284962011-06-20 23:28:09 +0200590 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000591 """Perform a read during which a signal will arrive. Return True if the
592 read is interrupted by the signal and raises an exception. Return False
593 if it returns normally.
594 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200595 # use a subprocess to have only one thread, to have a timeout on the
596 # blocking read and to not touch signal handling in this process
597 code = """if 1:
598 import errno
599 import os
600 import signal
601 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000602
Victor Stinnerd6284962011-06-20 23:28:09 +0200603 interrupt = %r
604 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000605
Victor Stinnerd6284962011-06-20 23:28:09 +0200606 def handler(signum, frame):
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000607 1 / 0
Victor Stinnerd6284962011-06-20 23:28:09 +0200608
609 signal.signal(signal.SIGALRM, handler)
610 if interrupt is not None:
611 signal.siginterrupt(signal.SIGALRM, interrupt)
612
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200613 print("ready")
614 sys.stdout.flush()
615
Victor Stinnerd6284962011-06-20 23:28:09 +0200616 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200617 try:
618 for loop in range(2):
619 # send a SIGALRM in a second (during the read)
620 signal.alarm(1)
621 try:
622 # blocking call: read from a pipe without data
623 os.read(r, 1)
Charles-François Natali6e6c59b2015-02-07 13:27:50 +0000624 except ZeroDivisionError:
625 pass
Victor Stinner56e8c292014-07-21 12:30:22 +0200626 else:
627 sys.exit(2)
628 sys.exit(3)
629 finally:
630 os.close(r)
631 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200632 """ % (interrupt,)
633 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000634 try:
Victor Stinner45273652011-06-22 22:15:51 +0200635 # wait until the child process is loaded and has started
636 first_line = process.stdout.readline()
637
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200638 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200639 except subprocess.TimeoutExpired:
640 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000641 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200642 else:
Victor Stinner45273652011-06-22 22:15:51 +0200643 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200644 exitcode = process.wait()
645 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200646 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200647 % (exitcode, stdout))
648 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000649
650 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200651 # If a signal handler is installed and siginterrupt is not called
652 # at all, when that signal arrives, it interrupts a syscall that's in
653 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200654 interrupted = self.readpipe_interrupted(None)
655 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000656
657 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200658 # If a signal handler is installed and siginterrupt is called with
659 # a true value for the second argument, when that signal arrives, it
660 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200661 interrupted = self.readpipe_interrupted(True)
662 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000663
664 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200665 # If a signal handler is installed and siginterrupt is called with
666 # a false value for the second argument, when that signal arrives, it
667 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200668 interrupted = self.readpipe_interrupted(False)
669 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000670
671
Brian Curtin3f004b12010-08-06 19:34:52 +0000672@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000673class ItimerTest(unittest.TestCase):
674 def setUp(self):
675 self.hndl_called = False
676 self.hndl_count = 0
677 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000678 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000679
680 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000681 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000682 if self.itimer is not None: # test_itimer_exc doesn't change this attr
683 # just ensure that itimer is stopped
684 signal.setitimer(self.itimer, 0)
685
686 def sig_alrm(self, *args):
687 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000688
689 def sig_vtalrm(self, *args):
690 self.hndl_called = True
691
692 if self.hndl_count > 3:
693 # it shouldn't be here, because it should have been disabled.
694 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
695 "timer.")
696 elif self.hndl_count == 3:
697 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
698 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000699
700 self.hndl_count += 1
701
Martin v. Löwis823725e2008-03-24 13:39:54 +0000702 def sig_prof(self, *args):
703 self.hndl_called = True
704 signal.setitimer(signal.ITIMER_PROF, 0)
705
Martin v. Löwis823725e2008-03-24 13:39:54 +0000706 def test_itimer_exc(self):
707 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
708 # defines it ?
709 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000710 # Negative times are treated as zero on some platforms.
711 if 0:
712 self.assertRaises(signal.ItimerError,
713 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000714
715 def test_itimer_real(self):
716 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000717 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000718 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000719 self.assertEqual(self.hndl_called, True)
720
R. David Murray44546f82010-04-21 01:59:28 +0000721 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000722 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
723 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000724 def test_itimer_virtual(self):
725 self.itimer = signal.ITIMER_VIRTUAL
726 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
727 signal.setitimer(self.itimer, 0.3, 0.2)
728
Victor Stinner79d68f92015-03-19 21:54:09 +0100729 start_time = time.monotonic()
730 while time.monotonic() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000731 # use up some virtual time by doing real work
732 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000733 if signal.getitimer(self.itimer) == (0.0, 0.0):
734 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000735 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000736 self.skipTest("timeout: likely cause: machine too slow or load too "
737 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000738
739 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000740 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000741 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000742 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000743
R. David Murray44546f82010-04-21 01:59:28 +0000744 # Issue 3864, unknown if this affects earlier versions of freebsd also
745 @unittest.skipIf(sys.platform=='freebsd6',
746 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000747 def test_itimer_prof(self):
748 self.itimer = signal.ITIMER_PROF
749 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000750 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000751
Victor Stinner79d68f92015-03-19 21:54:09 +0100752 start_time = time.monotonic()
753 while time.monotonic() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000754 # do some work
755 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000756 if signal.getitimer(self.itimer) == (0.0, 0.0):
757 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000758 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000759 self.skipTest("timeout: likely cause: machine too slow or load too "
760 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000761
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000762 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000763 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000764 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000765 self.assertEqual(self.hndl_called, True)
766
Victor Stinnera9293352011-04-30 15:21:58 +0200767
Victor Stinner35b300c2011-05-04 13:20:35 +0200768class PendingSignalsTests(unittest.TestCase):
769 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200770 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
771 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200772 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200773 @unittest.skipUnless(hasattr(signal, 'sigpending'),
774 'need signal.sigpending()')
775 def test_sigpending_empty(self):
776 self.assertEqual(signal.sigpending(), set())
777
778 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
779 'need signal.pthread_sigmask()')
780 @unittest.skipUnless(hasattr(signal, 'sigpending'),
781 'need signal.sigpending()')
782 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200783 code = """if 1:
784 import os
785 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200786
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200787 def handler(signum, frame):
788 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200789
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200790 signum = signal.SIGUSR1
791 signal.signal(signum, handler)
792
793 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
794 os.kill(os.getpid(), signum)
795 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200796 for sig in pending:
797 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200798 if pending != {signum}:
799 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200800 try:
801 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
802 except ZeroDivisionError:
803 pass
804 else:
805 raise Exception("ZeroDivisionError not raised")
806 """
807 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200808
809 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
810 'need signal.pthread_kill()')
811 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200812 code = """if 1:
813 import signal
814 import threading
815 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200816
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200817 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200818
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200819 def handler(signum, frame):
820 1/0
821
822 signal.signal(signum, handler)
823
824 if sys.platform == 'freebsd6':
825 # Issue #12392 and #12469: send a signal to the main thread
826 # doesn't work before the creation of the first thread on
827 # FreeBSD 6
828 def noop():
829 pass
830 thread = threading.Thread(target=noop)
831 thread.start()
832 thread.join()
833
834 tid = threading.get_ident()
835 try:
836 signal.pthread_kill(tid, signum)
837 except ZeroDivisionError:
838 pass
839 else:
840 raise Exception("ZeroDivisionError not raised")
841 """
842 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200843
Victor Stinner7f294d12011-06-10 14:02:10 +0200844 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
845 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200846 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200847 """
848 test: body of the "def test(signum):" function.
849 blocked: number of the blocked signal
850 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200851 code = '''if 1:
852 import signal
853 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200854 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200855
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200856 def handler(signum, frame):
857 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200858
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200859 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200860
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200861 blocked = %s
862 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200863
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200864 # child: block and wait the signal
865 try:
866 signal.signal(signum, handler)
867 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200868
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200869 # Do the tests
870 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200871
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200872 # The handler must not be called on unblock
873 try:
874 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
875 except ZeroDivisionError:
876 print("the signal handler has been called",
877 file=sys.stderr)
878 sys.exit(1)
879 except BaseException as err:
880 print("error: {}".format(err), file=sys.stderr)
881 sys.stderr.flush()
882 sys.exit(1)
883 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200884
Ross Lagerwallbc808222011-06-25 12:13:40 +0200885 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200886 # process might have several threads running, use a subprocess to have
887 # a single thread.
888 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200889
Victor Stinnerb3e72192011-05-08 01:46:11 +0200890 @unittest.skipUnless(hasattr(signal, 'sigwait'),
891 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200892 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200893 self.wait_helper(signal.SIGALRM, '''
894 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200895 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200896 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200897 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200898 if received != signum:
899 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200900 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200901
902 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
903 'need signal.sigwaitinfo()')
904 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200905 self.wait_helper(signal.SIGALRM, '''
906 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200907 signal.alarm(1)
908 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200909 if info.si_signo != signum:
910 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200911 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200912
913 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
914 'need signal.sigtimedwait()')
915 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200916 self.wait_helper(signal.SIGALRM, '''
917 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200918 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100919 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200920 if info.si_signo != signum:
921 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200922 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200923
Ross Lagerwallbc808222011-06-25 12:13:40 +0200924 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
925 'need signal.sigtimedwait()')
926 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200927 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200928 self.wait_helper(signal.SIGALRM, '''
929 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200930 import os
931 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100932 info = signal.sigtimedwait([signum], 0)
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
937 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
938 'need signal.sigtimedwait()')
939 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200940 self.wait_helper(signal.SIGALRM, '''
941 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100942 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200943 if received is not None:
944 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200945 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200946
947 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
948 'need signal.sigtimedwait()')
949 def test_sigtimedwait_negative_timeout(self):
950 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100951 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200952
Ross Lagerwallbc808222011-06-25 12:13:40 +0200953 @unittest.skipUnless(hasattr(signal, 'sigwait'),
954 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200955 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
956 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200957 @unittest.skipIf(threading is None, "test needs threading module")
958 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200959 # Check that calling sigwait() from a thread doesn't suspend the whole
960 # process. A new interpreter is spawned to avoid problems when mixing
961 # threads and fork(): only async-safe functions are allowed between
962 # fork() and exec().
963 assert_python_ok("-c", """if True:
964 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200965
Victor Stinner415007e2011-06-13 16:19:06 +0200966 # the default handler terminates the process
967 signum = signal.SIGUSR1
968
969 def kill_later():
970 # wait until the main thread is waiting in sigwait()
971 time.sleep(1)
972 os.kill(os.getpid(), signum)
973
974 # the signal must be blocked by all the threads
975 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
976 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200977 killer.start()
978 received = signal.sigwait([signum])
979 if received != signum:
980 print("sigwait() received %s, not %s" % (received, signum),
981 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200982 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200983 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200984 # unblock the signal, which should have been cleared by sigwait()
985 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
986 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200987
Victor Stinnerb3e72192011-05-08 01:46:11 +0200988 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
989 'need signal.pthread_sigmask()')
990 def test_pthread_sigmask_arguments(self):
991 self.assertRaises(TypeError, signal.pthread_sigmask)
992 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
993 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
994 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
995
996 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
997 'need signal.pthread_sigmask()')
998 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200999 code = """if 1:
1000 import signal
1001 import os; import threading
1002
1003 def handler(signum, frame):
1004 1/0
1005
1006 def kill(signum):
1007 os.kill(os.getpid(), signum)
1008
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001009 def check_mask(mask):
1010 for sig in mask:
1011 assert isinstance(sig, signal.Signals), repr(sig)
1012
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001013 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001014 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
1015 check_mask(sigmask)
1016 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001017
Victor Stinnerb3e72192011-05-08 01:46:11 +02001018 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +02001019
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001020 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001021 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +02001022
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001023 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +02001024 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001025 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001026 try:
1027 kill(signum)
1028 except ZeroDivisionError:
1029 pass
1030 else:
1031 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001032
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001033 # Block and then raise SIGUSR1. The signal is blocked: the signal
1034 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001035 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
1036 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001037 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +02001038
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001039 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001040 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001041 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +02001042 if signum not in blocked:
1043 raise Exception("%s not in %s" % (signum, blocked))
1044 if old_mask ^ blocked != {signum}:
1045 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +02001046
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001047 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001048 try:
R David Murrayfc069992013-12-13 20:52:19 -05001049 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001050 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001051 except ZeroDivisionError:
1052 pass
1053 else:
1054 raise Exception("ZeroDivisionError not raised")
1055 try:
1056 kill(signum)
1057 except ZeroDivisionError:
1058 pass
1059 else:
1060 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001061
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001062 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001063 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +02001064 if signum in unblocked:
1065 raise Exception("%s in %s" % (signum, unblocked))
1066 if blocked ^ unblocked != {signum}:
1067 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
1068 if old_mask != unblocked:
1069 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001070 """
1071 assert_python_ok('-c', code)
1072
1073 @unittest.skipIf(sys.platform == 'freebsd6',
1074 "issue #12392: send a signal to the main thread doesn't work "
1075 "before the creation of the first thread on FreeBSD 6")
1076 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
1077 'need signal.pthread_kill()')
1078 def test_pthread_kill_main_thread(self):
1079 # Test that a signal can be sent to the main thread with pthread_kill()
1080 # before any other thread has been created (see issue #12392).
1081 code = """if True:
1082 import threading
1083 import signal
1084 import sys
1085
1086 def handler(signum, frame):
1087 sys.exit(3)
1088
1089 signal.signal(signal.SIGUSR1, handler)
1090 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1091 sys.exit(2)
1092 """
1093
1094 with spawn_python('-c', code) as process:
1095 stdout, stderr = process.communicate()
1096 exitcode = process.wait()
1097 if exitcode != 3:
1098 raise Exception("Child error (exit code %s): %s" %
1099 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001100
1101
Zachary Ware38c707e2015-04-13 15:00:43 -05001102def tearDownModule():
1103 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001104
1105if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001106 unittest.main()