blob: 8f3dde4d4fef34c8b32d5ccbf412bd52d639417c [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
Victor Stinnerd6284962011-06-20 23:28:09 +020014from test.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
421 signal.alarm(1)
422 before_time = time.time()
423 # We attempt to get a signal during the sleep,
424 # before select is called
425 time.sleep(TIMEOUT_FULL)
426 mid_time = time.time()
427 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200428 if dt >= TIMEOUT_HALF:
429 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200430 select.select([read], [], [], TIMEOUT_FULL)
431 after_time = time.time()
432 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200433 if dt >= TIMEOUT_HALF:
434 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200435 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000436
437 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200438 self.check_wakeup("""def test():
439 import select
440 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000441
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200442 TIMEOUT_FULL = 10
443 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000444
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200445 signal.alarm(1)
446 before_time = time.time()
447 # We attempt to get a signal during the select call
448 try:
449 select.select([read], [], [], TIMEOUT_FULL)
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200450 except OSError:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200451 pass
452 else:
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200453 raise Exception("OSError not raised")
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200454 after_time = time.time()
455 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200456 if dt >= TIMEOUT_HALF:
457 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200458 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200459
460 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200461 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200462 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200463 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200464 _testcapi.raise_signal(signal.SIGUSR1)
465 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200466 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000467
Victor Stinnerc13ef662011-05-25 02:35:58 +0200468 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
469 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200470 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200471 self.check_wakeup("""def test():
472 signum1 = signal.SIGUSR1
473 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200474
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200475 signal.signal(signum1, handler)
476 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200477
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200478 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200479 _testcapi.raise_signal(signum1)
480 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200481 # Unblocking the 2 signals calls the C signal handler twice
482 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200483 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200484
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000485
Victor Stinner11517102014-07-29 23:31:34 +0200486@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
487class WakeupSocketSignalTests(unittest.TestCase):
488
489 @unittest.skipIf(_testcapi is None, 'need _testcapi')
490 def test_socket(self):
491 # use a subprocess to have only one thread
492 code = """if 1:
493 import signal
494 import socket
495 import struct
496 import _testcapi
497
498 signum = signal.SIGINT
499 signals = (signum,)
500
501 def handler(signum, frame):
502 pass
503
504 signal.signal(signum, handler)
505
506 read, write = socket.socketpair()
507 read.setblocking(False)
508 write.setblocking(False)
509 signal.set_wakeup_fd(write.fileno())
510
511 _testcapi.raise_signal(signum)
512
513 data = read.recv(1)
514 if not data:
515 raise Exception("no signum written")
516 raised = struct.unpack('B', data)
517 if raised != signals:
518 raise Exception("%r != %r" % (raised, signals))
519
520 read.close()
521 write.close()
522 """
523
524 assert_python_ok('-c', code)
525
526 @unittest.skipIf(_testcapi is None, 'need _testcapi')
527 def test_send_error(self):
528 # Use a subprocess to have only one thread.
529 if os.name == 'nt':
530 action = 'send'
531 else:
532 action = 'write'
533 code = """if 1:
534 import errno
535 import signal
536 import socket
537 import sys
538 import time
539 import _testcapi
540 from test.support import captured_stderr
541
542 signum = signal.SIGINT
543
544 def handler(signum, frame):
545 pass
546
547 signal.signal(signum, handler)
548
549 read, write = socket.socketpair()
550 read.setblocking(False)
551 write.setblocking(False)
552
553 signal.set_wakeup_fd(write.fileno())
554
555 # Close sockets: send() will fail
556 read.close()
557 write.close()
558
559 with captured_stderr() as err:
560 _testcapi.raise_signal(signum)
561
562 err = err.getvalue()
563 if ('Exception ignored when trying to {action} to the signal wakeup fd'
564 not in err):
565 raise AssertionError(err)
566 """.format(action=action)
567 assert_python_ok('-c', code)
568
569
Brian Curtin3f004b12010-08-06 19:34:52 +0000570@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000571class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000572
Victor Stinnerd6284962011-06-20 23:28:09 +0200573 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000574 """Perform a read during which a signal will arrive. Return True if the
575 read is interrupted by the signal and raises an exception. Return False
576 if it returns normally.
577 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200578 # use a subprocess to have only one thread, to have a timeout on the
579 # blocking read and to not touch signal handling in this process
580 code = """if 1:
581 import errno
582 import os
583 import signal
584 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000585
Victor Stinnerd6284962011-06-20 23:28:09 +0200586 interrupt = %r
587 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000588
Victor Stinnerd6284962011-06-20 23:28:09 +0200589 def handler(signum, frame):
590 pass
591
592 signal.signal(signal.SIGALRM, handler)
593 if interrupt is not None:
594 signal.siginterrupt(signal.SIGALRM, interrupt)
595
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200596 print("ready")
597 sys.stdout.flush()
598
Victor Stinnerd6284962011-06-20 23:28:09 +0200599 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200600 try:
601 for loop in range(2):
602 # send a SIGALRM in a second (during the read)
603 signal.alarm(1)
604 try:
605 # blocking call: read from a pipe without data
606 os.read(r, 1)
607 except OSError as err:
608 if err.errno != errno.EINTR:
609 raise
610 else:
611 sys.exit(2)
612 sys.exit(3)
613 finally:
614 os.close(r)
615 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200616 """ % (interrupt,)
617 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000618 try:
Victor Stinner45273652011-06-22 22:15:51 +0200619 # wait until the child process is loaded and has started
620 first_line = process.stdout.readline()
621
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200622 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200623 except subprocess.TimeoutExpired:
624 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000625 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200626 else:
Victor Stinner45273652011-06-22 22:15:51 +0200627 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200628 exitcode = process.wait()
629 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200630 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200631 % (exitcode, stdout))
632 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000633
634 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200635 # If a signal handler is installed and siginterrupt is not called
636 # at all, when that signal arrives, it interrupts a syscall that's in
637 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200638 interrupted = self.readpipe_interrupted(None)
639 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000640
641 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200642 # If a signal handler is installed and siginterrupt is called with
643 # a true value for the second argument, when that signal arrives, it
644 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200645 interrupted = self.readpipe_interrupted(True)
646 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000647
648 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200649 # If a signal handler is installed and siginterrupt is called with
650 # a false value for the second argument, when that signal arrives, it
651 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200652 interrupted = self.readpipe_interrupted(False)
653 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000654
655
Brian Curtin3f004b12010-08-06 19:34:52 +0000656@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000657class ItimerTest(unittest.TestCase):
658 def setUp(self):
659 self.hndl_called = False
660 self.hndl_count = 0
661 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000662 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000663
664 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000665 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000666 if self.itimer is not None: # test_itimer_exc doesn't change this attr
667 # just ensure that itimer is stopped
668 signal.setitimer(self.itimer, 0)
669
670 def sig_alrm(self, *args):
671 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000672
673 def sig_vtalrm(self, *args):
674 self.hndl_called = True
675
676 if self.hndl_count > 3:
677 # it shouldn't be here, because it should have been disabled.
678 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
679 "timer.")
680 elif self.hndl_count == 3:
681 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
682 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000683
684 self.hndl_count += 1
685
Martin v. Löwis823725e2008-03-24 13:39:54 +0000686 def sig_prof(self, *args):
687 self.hndl_called = True
688 signal.setitimer(signal.ITIMER_PROF, 0)
689
Martin v. Löwis823725e2008-03-24 13:39:54 +0000690 def test_itimer_exc(self):
691 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
692 # defines it ?
693 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000694 # Negative times are treated as zero on some platforms.
695 if 0:
696 self.assertRaises(signal.ItimerError,
697 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000698
699 def test_itimer_real(self):
700 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000701 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000702 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000703 self.assertEqual(self.hndl_called, True)
704
R. David Murray44546f82010-04-21 01:59:28 +0000705 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000706 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
707 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000708 def test_itimer_virtual(self):
709 self.itimer = signal.ITIMER_VIRTUAL
710 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
711 signal.setitimer(self.itimer, 0.3, 0.2)
712
Mark Dickinson78373472009-10-31 10:39:21 +0000713 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000714 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000715 # use up some virtual time by doing real work
716 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000717 if signal.getitimer(self.itimer) == (0.0, 0.0):
718 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000719 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000720 self.skipTest("timeout: likely cause: machine too slow or load too "
721 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000722
723 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000724 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000725 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000726 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000727
R. David Murray44546f82010-04-21 01:59:28 +0000728 # Issue 3864, unknown if this affects earlier versions of freebsd also
729 @unittest.skipIf(sys.platform=='freebsd6',
730 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000731 def test_itimer_prof(self):
732 self.itimer = signal.ITIMER_PROF
733 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000734 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000735
Mark Dickinson78373472009-10-31 10:39:21 +0000736 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000737 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000738 # do some work
739 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000740 if signal.getitimer(self.itimer) == (0.0, 0.0):
741 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000742 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000743 self.skipTest("timeout: likely cause: machine too slow or load too "
744 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000745
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000746 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000747 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000748 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000749 self.assertEqual(self.hndl_called, True)
750
Victor Stinnera9293352011-04-30 15:21:58 +0200751
Victor Stinner35b300c2011-05-04 13:20:35 +0200752class PendingSignalsTests(unittest.TestCase):
753 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200754 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
755 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200756 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200757 @unittest.skipUnless(hasattr(signal, 'sigpending'),
758 'need signal.sigpending()')
759 def test_sigpending_empty(self):
760 self.assertEqual(signal.sigpending(), set())
761
762 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
763 'need signal.pthread_sigmask()')
764 @unittest.skipUnless(hasattr(signal, 'sigpending'),
765 'need signal.sigpending()')
766 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200767 code = """if 1:
768 import os
769 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200770
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200771 def handler(signum, frame):
772 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200773
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200774 signum = signal.SIGUSR1
775 signal.signal(signum, handler)
776
777 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
778 os.kill(os.getpid(), signum)
779 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200780 for sig in pending:
781 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200782 if pending != {signum}:
783 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200784 try:
785 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
786 except ZeroDivisionError:
787 pass
788 else:
789 raise Exception("ZeroDivisionError not raised")
790 """
791 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200792
793 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
794 'need signal.pthread_kill()')
795 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200796 code = """if 1:
797 import signal
798 import threading
799 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200800
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200801 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200802
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200803 def handler(signum, frame):
804 1/0
805
806 signal.signal(signum, handler)
807
808 if sys.platform == 'freebsd6':
809 # Issue #12392 and #12469: send a signal to the main thread
810 # doesn't work before the creation of the first thread on
811 # FreeBSD 6
812 def noop():
813 pass
814 thread = threading.Thread(target=noop)
815 thread.start()
816 thread.join()
817
818 tid = threading.get_ident()
819 try:
820 signal.pthread_kill(tid, signum)
821 except ZeroDivisionError:
822 pass
823 else:
824 raise Exception("ZeroDivisionError not raised")
825 """
826 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200827
Victor Stinner7f294d12011-06-10 14:02:10 +0200828 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
829 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200830 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200831 """
832 test: body of the "def test(signum):" function.
833 blocked: number of the blocked signal
834 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200835 code = '''if 1:
836 import signal
837 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200838 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200839
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200840 def handler(signum, frame):
841 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200842
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200843 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200844
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200845 blocked = %s
846 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200847
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200848 # child: block and wait the signal
849 try:
850 signal.signal(signum, handler)
851 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200852
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200853 # Do the tests
854 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200855
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200856 # The handler must not be called on unblock
857 try:
858 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
859 except ZeroDivisionError:
860 print("the signal handler has been called",
861 file=sys.stderr)
862 sys.exit(1)
863 except BaseException as err:
864 print("error: {}".format(err), file=sys.stderr)
865 sys.stderr.flush()
866 sys.exit(1)
867 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200868
Ross Lagerwallbc808222011-06-25 12:13:40 +0200869 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200870 # process might have several threads running, use a subprocess to have
871 # a single thread.
872 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200873
Victor Stinnerb3e72192011-05-08 01:46:11 +0200874 @unittest.skipUnless(hasattr(signal, 'sigwait'),
875 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200876 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200877 self.wait_helper(signal.SIGALRM, '''
878 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200879 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200880 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200881 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200882 if received != signum:
883 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200884 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200885
886 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
887 'need signal.sigwaitinfo()')
888 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200889 self.wait_helper(signal.SIGALRM, '''
890 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200891 signal.alarm(1)
892 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200893 if info.si_signo != signum:
894 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200895 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200896
897 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
898 'need signal.sigtimedwait()')
899 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200900 self.wait_helper(signal.SIGALRM, '''
901 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200902 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100903 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200904 if info.si_signo != signum:
905 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200906 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200907
Ross Lagerwallbc808222011-06-25 12:13:40 +0200908 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
909 'need signal.sigtimedwait()')
910 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200911 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200912 self.wait_helper(signal.SIGALRM, '''
913 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200914 import os
915 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100916 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200917 if info.si_signo != signum:
918 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200919 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200920
921 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
922 'need signal.sigtimedwait()')
923 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200924 self.wait_helper(signal.SIGALRM, '''
925 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100926 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200927 if received is not None:
928 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200929 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200930
931 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
932 'need signal.sigtimedwait()')
933 def test_sigtimedwait_negative_timeout(self):
934 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100935 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200936
Ross Lagerwallbc808222011-06-25 12:13:40 +0200937 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
938 'need signal.sigwaitinfo()')
Victor Stinner91f9bdd2013-06-17 21:51:56 +0200939 # Issue #18238: sigwaitinfo() can be interrupted on Linux (raises
940 # InterruptedError), but not on AIX
941 @unittest.skipIf(sys.platform.startswith("aix"),
942 'signal.sigwaitinfo() cannot be interrupted on AIX')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200943 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200944 self.wait_helper(signal.SIGUSR1, '''
945 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200946 import errno
947
948 hndl_called = True
949 def alarm_handler(signum, frame):
950 hndl_called = False
951
952 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200953 signal.alarm(1)
954 try:
955 signal.sigwaitinfo([signal.SIGUSR1])
956 except OSError as e:
957 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200958 if not hndl_called:
959 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200960 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200961 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200962 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200963 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200964 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200965
966 @unittest.skipUnless(hasattr(signal, 'sigwait'),
967 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200968 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
969 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200970 @unittest.skipIf(threading is None, "test needs threading module")
971 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200972 # Check that calling sigwait() from a thread doesn't suspend the whole
973 # process. A new interpreter is spawned to avoid problems when mixing
974 # threads and fork(): only async-safe functions are allowed between
975 # fork() and exec().
976 assert_python_ok("-c", """if True:
977 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200978
Victor Stinner415007e2011-06-13 16:19:06 +0200979 # the default handler terminates the process
980 signum = signal.SIGUSR1
981
982 def kill_later():
983 # wait until the main thread is waiting in sigwait()
984 time.sleep(1)
985 os.kill(os.getpid(), signum)
986
987 # the signal must be blocked by all the threads
988 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
989 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200990 killer.start()
991 received = signal.sigwait([signum])
992 if received != signum:
993 print("sigwait() received %s, not %s" % (received, signum),
994 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200995 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200996 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200997 # unblock the signal, which should have been cleared by sigwait()
998 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
999 """)
Victor Stinneraf494602011-06-10 12:48:13 +02001000
Victor Stinnerb3e72192011-05-08 01:46:11 +02001001 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
1002 'need signal.pthread_sigmask()')
1003 def test_pthread_sigmask_arguments(self):
1004 self.assertRaises(TypeError, signal.pthread_sigmask)
1005 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
1006 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
1007 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
1008
1009 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
1010 'need signal.pthread_sigmask()')
1011 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001012 code = """if 1:
1013 import signal
1014 import os; import threading
1015
1016 def handler(signum, frame):
1017 1/0
1018
1019 def kill(signum):
1020 os.kill(os.getpid(), signum)
1021
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001022 def check_mask(mask):
1023 for sig in mask:
1024 assert isinstance(sig, signal.Signals), repr(sig)
1025
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001026 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001027 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
1028 check_mask(sigmask)
1029 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001030
Victor Stinnerb3e72192011-05-08 01:46:11 +02001031 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +02001032
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001033 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001034 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +02001035
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001036 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +02001037 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001038 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001039 try:
1040 kill(signum)
1041 except ZeroDivisionError:
1042 pass
1043 else:
1044 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001045
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001046 # Block and then raise SIGUSR1. The signal is blocked: the signal
1047 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001048 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
1049 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001050 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +02001051
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001052 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001053 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001054 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +02001055 if signum not in blocked:
1056 raise Exception("%s not in %s" % (signum, blocked))
1057 if old_mask ^ blocked != {signum}:
1058 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +02001059
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001060 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001061 try:
R David Murrayfc069992013-12-13 20:52:19 -05001062 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001063 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001064 except ZeroDivisionError:
1065 pass
1066 else:
1067 raise Exception("ZeroDivisionError not raised")
1068 try:
1069 kill(signum)
1070 except ZeroDivisionError:
1071 pass
1072 else:
1073 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001074
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001075 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001076 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +02001077 if signum in unblocked:
1078 raise Exception("%s in %s" % (signum, unblocked))
1079 if blocked ^ unblocked != {signum}:
1080 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
1081 if old_mask != unblocked:
1082 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001083 """
1084 assert_python_ok('-c', code)
1085
1086 @unittest.skipIf(sys.platform == 'freebsd6',
1087 "issue #12392: send a signal to the main thread doesn't work "
1088 "before the creation of the first thread on FreeBSD 6")
1089 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
1090 'need signal.pthread_kill()')
1091 def test_pthread_kill_main_thread(self):
1092 # Test that a signal can be sent to the main thread with pthread_kill()
1093 # before any other thread has been created (see issue #12392).
1094 code = """if True:
1095 import threading
1096 import signal
1097 import sys
1098
1099 def handler(signum, frame):
1100 sys.exit(3)
1101
1102 signal.signal(signal.SIGUSR1, handler)
1103 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1104 sys.exit(2)
1105 """
1106
1107 with spawn_python('-c', code) as process:
1108 stdout, stderr = process.communicate()
1109 exitcode = process.wait()
1110 if exitcode != 3:
1111 raise Exception("Child error (exit code %s): %s" %
1112 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001113
1114
Thomas Woutersed03b412007-08-28 21:37:11 +00001115def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +01001116 try:
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001117 support.run_unittest(GenericTests, PosixTests, InterProcessSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -05001118 WakeupFDTests, WakeupSignalTests,
Victor Stinner11517102014-07-29 23:31:34 +02001119 WakeupSocketSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -05001120 SiginterruptTest, ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +02001121 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +01001122 finally:
1123 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001124
1125
1126if __name__ == "__main__":
1127 test_main()