blob: 57b0d8657e828ab3f2317b186e40f4e02c91e51e [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 Stinner1d8948e2014-07-24 22:51:05 +0200274 signal.set_wakeup_fd(w1)
Victor Stinnerc82a1792014-07-24 22:55:12 +0200275 self.assertEqual(signal.set_wakeup_fd(w2), w1)
276 self.assertEqual(signal.set_wakeup_fd(-1), w2)
277 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner56e8c292014-07-21 12:30:22 +0200278
Victor Stinner11517102014-07-29 23:31:34 +0200279 def test_set_wakeup_fd_socket_result(self):
280 sock1 = socket.socket()
281 self.addCleanup(sock1.close)
282 fd1 = sock1.fileno()
283
284 sock2 = socket.socket()
285 self.addCleanup(sock2.close)
286 fd2 = sock2.fileno()
287
288 signal.set_wakeup_fd(fd1)
Victor Stinnerda565a72014-07-30 10:03:03 +0200289 self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
290 self.assertEqual(signal.set_wakeup_fd(-1), fd2)
291 self.assertEqual(signal.set_wakeup_fd(-1), -1)
Victor Stinner11517102014-07-29 23:31:34 +0200292
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500293
Brian Curtin3f004b12010-08-06 19:34:52 +0000294@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000295class WakeupSignalTests(unittest.TestCase):
Victor Stinner56e8c292014-07-21 12:30:22 +0200296 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Charles-François Natali027f9a32011-10-02 18:36:05 +0200297 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200298 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200299 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200300 import _testcapi
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200301 import os
302 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200303 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000304
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200305 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200306
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200307 def handler(signum, frame):
308 pass
309
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200310 def check_signum(signals):
311 data = os.read(read, len(signals)+1)
312 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200313 if not {!r}:
314 raised = set(raised)
315 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200316 if raised != signals:
317 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200318
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200319 {}
320
321 signal.signal(signal.SIGALRM, handler)
322 read, write = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200323 os.set_blocking(write, False)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200324 signal.set_wakeup_fd(write)
325
326 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200327 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200328
329 os.close(read)
330 os.close(write)
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200331 """.format(tuple(map(int, signals)), ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200332
333 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200334
Victor Stinner56e8c292014-07-21 12:30:22 +0200335 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200336 def test_wakeup_write_error(self):
337 # Issue #16105: write() errors in the C signal handler should not
338 # pass silently.
339 # Use a subprocess to have only one thread.
340 code = """if 1:
Victor Stinner56e8c292014-07-21 12:30:22 +0200341 import _testcapi
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200342 import errno
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200343 import os
344 import signal
345 import sys
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200346 from test.support import captured_stderr
347
348 def handler(signum, frame):
349 1/0
350
351 signal.signal(signal.SIGALRM, handler)
352 r, w = os.pipe()
Victor Stinner1db9e7b2014-07-29 22:32:47 +0200353 os.set_blocking(r, False)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200354
355 # Set wakeup_fd a read-only file descriptor to trigger the error
356 signal.set_wakeup_fd(r)
357 try:
358 with captured_stderr() as err:
Victor Stinner56e8c292014-07-21 12:30:22 +0200359 _testcapi.raise_signal(signal.SIGALRM)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200360 except ZeroDivisionError:
361 # An ignored exception should have been printed out on stderr
362 err = err.getvalue()
363 if ('Exception ignored when trying to write to the signal wakeup fd'
364 not in err):
365 raise AssertionError(err)
366 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
367 raise AssertionError(err)
368 else:
369 raise AssertionError("ZeroDivisionError not raised")
Victor Stinner56e8c292014-07-21 12:30:22 +0200370
371 os.close(r)
372 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200373 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200374 r, w = os.pipe()
375 try:
376 os.write(r, b'x')
377 except OSError:
378 pass
379 else:
380 self.skipTest("OS doesn't report write() error on the read end of a pipe")
381 finally:
382 os.close(r)
383 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200384
385 assert_python_ok('-c', code)
386
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000387 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200388 self.check_wakeup("""def test():
389 import select
390 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000391
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200392 TIMEOUT_FULL = 10
393 TIMEOUT_HALF = 5
394
395 signal.alarm(1)
396 before_time = time.time()
397 # We attempt to get a signal during the sleep,
398 # before select is called
399 time.sleep(TIMEOUT_FULL)
400 mid_time = time.time()
401 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200402 if dt >= TIMEOUT_HALF:
403 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200404 select.select([read], [], [], TIMEOUT_FULL)
405 after_time = time.time()
406 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200407 if dt >= TIMEOUT_HALF:
408 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200409 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000410
411 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200412 self.check_wakeup("""def test():
413 import select
414 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000415
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200416 TIMEOUT_FULL = 10
417 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000418
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200419 signal.alarm(1)
420 before_time = time.time()
421 # We attempt to get a signal during the select call
422 try:
423 select.select([read], [], [], TIMEOUT_FULL)
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200424 except OSError:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200425 pass
426 else:
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200427 raise Exception("OSError not raised")
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200428 after_time = time.time()
429 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200430 if dt >= TIMEOUT_HALF:
431 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200432 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200433
434 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200435 self.check_wakeup("""def test():
Victor Stinner56e8c292014-07-21 12:30:22 +0200436 import _testcapi
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200437 signal.signal(signal.SIGUSR1, handler)
Victor Stinner56e8c292014-07-21 12:30:22 +0200438 _testcapi.raise_signal(signal.SIGUSR1)
439 _testcapi.raise_signal(signal.SIGALRM)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200440 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000441
Victor Stinnerc13ef662011-05-25 02:35:58 +0200442 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
443 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200444 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200445 self.check_wakeup("""def test():
446 signum1 = signal.SIGUSR1
447 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200448
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200449 signal.signal(signum1, handler)
450 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200451
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200452 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
Victor Stinner56e8c292014-07-21 12:30:22 +0200453 _testcapi.raise_signal(signum1)
454 _testcapi.raise_signal(signum2)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200455 # Unblocking the 2 signals calls the C signal handler twice
456 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200457 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200458
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000459
Victor Stinner11517102014-07-29 23:31:34 +0200460@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
461class WakeupSocketSignalTests(unittest.TestCase):
462
463 @unittest.skipIf(_testcapi is None, 'need _testcapi')
464 def test_socket(self):
465 # use a subprocess to have only one thread
466 code = """if 1:
467 import signal
468 import socket
469 import struct
470 import _testcapi
471
472 signum = signal.SIGINT
473 signals = (signum,)
474
475 def handler(signum, frame):
476 pass
477
478 signal.signal(signum, handler)
479
480 read, write = socket.socketpair()
481 read.setblocking(False)
482 write.setblocking(False)
483 signal.set_wakeup_fd(write.fileno())
484
485 _testcapi.raise_signal(signum)
486
487 data = read.recv(1)
488 if not data:
489 raise Exception("no signum written")
490 raised = struct.unpack('B', data)
491 if raised != signals:
492 raise Exception("%r != %r" % (raised, signals))
493
494 read.close()
495 write.close()
496 """
497
498 assert_python_ok('-c', code)
499
500 @unittest.skipIf(_testcapi is None, 'need _testcapi')
501 def test_send_error(self):
502 # Use a subprocess to have only one thread.
503 if os.name == 'nt':
504 action = 'send'
505 else:
506 action = 'write'
507 code = """if 1:
508 import errno
509 import signal
510 import socket
511 import sys
512 import time
513 import _testcapi
514 from test.support import captured_stderr
515
516 signum = signal.SIGINT
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
527 signal.set_wakeup_fd(write.fileno())
528
529 # Close sockets: send() will fail
530 read.close()
531 write.close()
532
533 with captured_stderr() as err:
534 _testcapi.raise_signal(signum)
535
536 err = err.getvalue()
537 if ('Exception ignored when trying to {action} to the signal wakeup fd'
538 not in err):
539 raise AssertionError(err)
540 """.format(action=action)
541 assert_python_ok('-c', code)
542
543
Brian Curtin3f004b12010-08-06 19:34:52 +0000544@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000545class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000546
Victor Stinnerd6284962011-06-20 23:28:09 +0200547 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000548 """Perform a read during which a signal will arrive. Return True if the
549 read is interrupted by the signal and raises an exception. Return False
550 if it returns normally.
551 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200552 # use a subprocess to have only one thread, to have a timeout on the
553 # blocking read and to not touch signal handling in this process
554 code = """if 1:
555 import errno
556 import os
557 import signal
558 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000559
Victor Stinnerd6284962011-06-20 23:28:09 +0200560 interrupt = %r
561 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000562
Victor Stinnerd6284962011-06-20 23:28:09 +0200563 def handler(signum, frame):
564 pass
565
566 signal.signal(signal.SIGALRM, handler)
567 if interrupt is not None:
568 signal.siginterrupt(signal.SIGALRM, interrupt)
569
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200570 print("ready")
571 sys.stdout.flush()
572
Victor Stinnerd6284962011-06-20 23:28:09 +0200573 # run the test twice
Victor Stinner56e8c292014-07-21 12:30:22 +0200574 try:
575 for loop in range(2):
576 # send a SIGALRM in a second (during the read)
577 signal.alarm(1)
578 try:
579 # blocking call: read from a pipe without data
580 os.read(r, 1)
581 except OSError as err:
582 if err.errno != errno.EINTR:
583 raise
584 else:
585 sys.exit(2)
586 sys.exit(3)
587 finally:
588 os.close(r)
589 os.close(w)
Victor Stinnerd6284962011-06-20 23:28:09 +0200590 """ % (interrupt,)
591 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000592 try:
Victor Stinner45273652011-06-22 22:15:51 +0200593 # wait until the child process is loaded and has started
594 first_line = process.stdout.readline()
595
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200596 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200597 except subprocess.TimeoutExpired:
598 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000599 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200600 else:
Victor Stinner45273652011-06-22 22:15:51 +0200601 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200602 exitcode = process.wait()
603 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200604 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200605 % (exitcode, stdout))
606 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000607
608 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200609 # If a signal handler is installed and siginterrupt is not called
610 # at all, when that signal arrives, it interrupts a syscall that's in
611 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200612 interrupted = self.readpipe_interrupted(None)
613 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000614
615 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200616 # If a signal handler is installed and siginterrupt is called with
617 # a true value for the second argument, when that signal arrives, it
618 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200619 interrupted = self.readpipe_interrupted(True)
620 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000621
622 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200623 # If a signal handler is installed and siginterrupt is called with
624 # a false value for the second argument, when that signal arrives, it
625 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200626 interrupted = self.readpipe_interrupted(False)
627 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000628
629
Brian Curtin3f004b12010-08-06 19:34:52 +0000630@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000631class ItimerTest(unittest.TestCase):
632 def setUp(self):
633 self.hndl_called = False
634 self.hndl_count = 0
635 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000636 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000637
638 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000639 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000640 if self.itimer is not None: # test_itimer_exc doesn't change this attr
641 # just ensure that itimer is stopped
642 signal.setitimer(self.itimer, 0)
643
644 def sig_alrm(self, *args):
645 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000646
647 def sig_vtalrm(self, *args):
648 self.hndl_called = True
649
650 if self.hndl_count > 3:
651 # it shouldn't be here, because it should have been disabled.
652 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
653 "timer.")
654 elif self.hndl_count == 3:
655 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
656 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000657
658 self.hndl_count += 1
659
Martin v. Löwis823725e2008-03-24 13:39:54 +0000660 def sig_prof(self, *args):
661 self.hndl_called = True
662 signal.setitimer(signal.ITIMER_PROF, 0)
663
Martin v. Löwis823725e2008-03-24 13:39:54 +0000664 def test_itimer_exc(self):
665 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
666 # defines it ?
667 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000668 # Negative times are treated as zero on some platforms.
669 if 0:
670 self.assertRaises(signal.ItimerError,
671 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000672
673 def test_itimer_real(self):
674 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000675 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000676 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000677 self.assertEqual(self.hndl_called, True)
678
R. David Murray44546f82010-04-21 01:59:28 +0000679 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000680 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
681 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000682 def test_itimer_virtual(self):
683 self.itimer = signal.ITIMER_VIRTUAL
684 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
685 signal.setitimer(self.itimer, 0.3, 0.2)
686
Mark Dickinson78373472009-10-31 10:39:21 +0000687 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000688 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000689 # use up some virtual time by doing real work
690 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000691 if signal.getitimer(self.itimer) == (0.0, 0.0):
692 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000693 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000694 self.skipTest("timeout: likely cause: machine too slow or load too "
695 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000696
697 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000698 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000699 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000700 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000701
R. David Murray44546f82010-04-21 01:59:28 +0000702 # Issue 3864, unknown if this affects earlier versions of freebsd also
703 @unittest.skipIf(sys.platform=='freebsd6',
704 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000705 def test_itimer_prof(self):
706 self.itimer = signal.ITIMER_PROF
707 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000708 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000709
Mark Dickinson78373472009-10-31 10:39:21 +0000710 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000711 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000712 # do some work
713 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000714 if signal.getitimer(self.itimer) == (0.0, 0.0):
715 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000716 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000717 self.skipTest("timeout: likely cause: machine too slow or load too "
718 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000719
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000720 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000721 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000722 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000723 self.assertEqual(self.hndl_called, True)
724
Victor Stinnera9293352011-04-30 15:21:58 +0200725
Victor Stinner35b300c2011-05-04 13:20:35 +0200726class PendingSignalsTests(unittest.TestCase):
727 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200728 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
729 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200730 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200731 @unittest.skipUnless(hasattr(signal, 'sigpending'),
732 'need signal.sigpending()')
733 def test_sigpending_empty(self):
734 self.assertEqual(signal.sigpending(), set())
735
736 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
737 'need signal.pthread_sigmask()')
738 @unittest.skipUnless(hasattr(signal, 'sigpending'),
739 'need signal.sigpending()')
740 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200741 code = """if 1:
742 import os
743 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200744
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200745 def handler(signum, frame):
746 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200747
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200748 signum = signal.SIGUSR1
749 signal.signal(signum, handler)
750
751 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
752 os.kill(os.getpid(), signum)
753 pending = signal.sigpending()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200754 for sig in pending:
755 assert isinstance(sig, signal.Signals), repr(pending)
Victor Stinner0a01f132011-07-04 18:06:35 +0200756 if pending != {signum}:
757 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200758 try:
759 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
760 except ZeroDivisionError:
761 pass
762 else:
763 raise Exception("ZeroDivisionError not raised")
764 """
765 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200766
767 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
768 'need signal.pthread_kill()')
769 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200770 code = """if 1:
771 import signal
772 import threading
773 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200774
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200775 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200776
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200777 def handler(signum, frame):
778 1/0
779
780 signal.signal(signum, handler)
781
782 if sys.platform == 'freebsd6':
783 # Issue #12392 and #12469: send a signal to the main thread
784 # doesn't work before the creation of the first thread on
785 # FreeBSD 6
786 def noop():
787 pass
788 thread = threading.Thread(target=noop)
789 thread.start()
790 thread.join()
791
792 tid = threading.get_ident()
793 try:
794 signal.pthread_kill(tid, signum)
795 except ZeroDivisionError:
796 pass
797 else:
798 raise Exception("ZeroDivisionError not raised")
799 """
800 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200801
Victor Stinner7f294d12011-06-10 14:02:10 +0200802 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
803 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200804 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200805 """
806 test: body of the "def test(signum):" function.
807 blocked: number of the blocked signal
808 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200809 code = '''if 1:
810 import signal
811 import sys
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200812 from signal import Signals
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200813
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200814 def handler(signum, frame):
815 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200816
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200817 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200818
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200819 blocked = %s
820 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200821
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200822 # child: block and wait the signal
823 try:
824 signal.signal(signum, handler)
825 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200826
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200827 # Do the tests
828 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200829
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200830 # The handler must not be called on unblock
831 try:
832 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
833 except ZeroDivisionError:
834 print("the signal handler has been called",
835 file=sys.stderr)
836 sys.exit(1)
837 except BaseException as err:
838 print("error: {}".format(err), file=sys.stderr)
839 sys.stderr.flush()
840 sys.exit(1)
841 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200842
Ross Lagerwallbc808222011-06-25 12:13:40 +0200843 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200844 # process might have several threads running, use a subprocess to have
845 # a single thread.
846 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200847
Victor Stinnerb3e72192011-05-08 01:46:11 +0200848 @unittest.skipUnless(hasattr(signal, 'sigwait'),
849 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200850 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200851 self.wait_helper(signal.SIGALRM, '''
852 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200853 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200854 received = signal.sigwait([signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200855 assert isinstance(received, signal.Signals), received
Victor Stinner0a01f132011-07-04 18:06:35 +0200856 if received != signum:
857 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200858 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200859
860 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
861 'need signal.sigwaitinfo()')
862 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200863 self.wait_helper(signal.SIGALRM, '''
864 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200865 signal.alarm(1)
866 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200867 if info.si_signo != signum:
868 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200869 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200870
871 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
872 'need signal.sigtimedwait()')
873 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200874 self.wait_helper(signal.SIGALRM, '''
875 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200876 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100877 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200878 if info.si_signo != signum:
879 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200880 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200881
Ross Lagerwallbc808222011-06-25 12:13:40 +0200882 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
883 'need signal.sigtimedwait()')
884 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200885 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200886 self.wait_helper(signal.SIGALRM, '''
887 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200888 import os
889 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100890 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200891 if info.si_signo != signum:
892 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200893 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200894
895 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
896 'need signal.sigtimedwait()')
897 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200898 self.wait_helper(signal.SIGALRM, '''
899 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100900 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200901 if received is not None:
902 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200903 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200904
905 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
906 'need signal.sigtimedwait()')
907 def test_sigtimedwait_negative_timeout(self):
908 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100909 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200910
Ross Lagerwallbc808222011-06-25 12:13:40 +0200911 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
912 'need signal.sigwaitinfo()')
Victor Stinner91f9bdd2013-06-17 21:51:56 +0200913 # Issue #18238: sigwaitinfo() can be interrupted on Linux (raises
914 # InterruptedError), but not on AIX
915 @unittest.skipIf(sys.platform.startswith("aix"),
916 'signal.sigwaitinfo() cannot be interrupted on AIX')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200917 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200918 self.wait_helper(signal.SIGUSR1, '''
919 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200920 import errno
921
922 hndl_called = True
923 def alarm_handler(signum, frame):
924 hndl_called = False
925
926 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200927 signal.alarm(1)
928 try:
929 signal.sigwaitinfo([signal.SIGUSR1])
930 except OSError as e:
931 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200932 if not hndl_called:
933 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200934 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200935 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200936 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200937 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200938 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200939
940 @unittest.skipUnless(hasattr(signal, 'sigwait'),
941 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200942 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
943 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200944 @unittest.skipIf(threading is None, "test needs threading module")
945 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200946 # Check that calling sigwait() from a thread doesn't suspend the whole
947 # process. A new interpreter is spawned to avoid problems when mixing
948 # threads and fork(): only async-safe functions are allowed between
949 # fork() and exec().
950 assert_python_ok("-c", """if True:
951 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200952
Victor Stinner415007e2011-06-13 16:19:06 +0200953 # the default handler terminates the process
954 signum = signal.SIGUSR1
955
956 def kill_later():
957 # wait until the main thread is waiting in sigwait()
958 time.sleep(1)
959 os.kill(os.getpid(), signum)
960
961 # the signal must be blocked by all the threads
962 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
963 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200964 killer.start()
965 received = signal.sigwait([signum])
966 if received != signum:
967 print("sigwait() received %s, not %s" % (received, signum),
968 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200969 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200970 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200971 # unblock the signal, which should have been cleared by sigwait()
972 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
973 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200974
Victor Stinnerb3e72192011-05-08 01:46:11 +0200975 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
976 'need signal.pthread_sigmask()')
977 def test_pthread_sigmask_arguments(self):
978 self.assertRaises(TypeError, signal.pthread_sigmask)
979 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
980 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
981 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
982
983 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
984 'need signal.pthread_sigmask()')
985 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200986 code = """if 1:
987 import signal
988 import os; import threading
989
990 def handler(signum, frame):
991 1/0
992
993 def kill(signum):
994 os.kill(os.getpid(), signum)
995
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +0200996 def check_mask(mask):
997 for sig in mask:
998 assert isinstance(sig, signal.Signals), repr(sig)
999
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001000 def read_sigmask():
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001001 sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
1002 check_mask(sigmask)
1003 return sigmask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001004
Victor Stinnerb3e72192011-05-08 01:46:11 +02001005 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +02001006
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001007 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001008 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +02001009
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001010 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +02001011 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001012 check_mask(old_mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001013 try:
1014 kill(signum)
1015 except ZeroDivisionError:
1016 pass
1017 else:
1018 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001019
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001020 # Block and then raise SIGUSR1. The signal is blocked: the signal
1021 # handler is not called, and the signal is now pending
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001022 mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
1023 check_mask(mask)
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001024 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +02001025
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001026 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001027 blocked = read_sigmask()
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001028 check_mask(blocked)
Victor Stinner0a01f132011-07-04 18:06:35 +02001029 if signum not in blocked:
1030 raise Exception("%s not in %s" % (signum, blocked))
1031 if old_mask ^ blocked != {signum}:
1032 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +02001033
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001034 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001035 try:
R David Murrayfc069992013-12-13 20:52:19 -05001036 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001037 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001038 except ZeroDivisionError:
1039 pass
1040 else:
1041 raise Exception("ZeroDivisionError not raised")
1042 try:
1043 kill(signum)
1044 except ZeroDivisionError:
1045 pass
1046 else:
1047 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +02001048
Victor Stinnerd0e516d2011-05-03 14:57:12 +02001049 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001050 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +02001051 if signum in unblocked:
1052 raise Exception("%s in %s" % (signum, unblocked))
1053 if blocked ^ unblocked != {signum}:
1054 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
1055 if old_mask != unblocked:
1056 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +02001057 """
1058 assert_python_ok('-c', code)
1059
1060 @unittest.skipIf(sys.platform == 'freebsd6',
1061 "issue #12392: send a signal to the main thread doesn't work "
1062 "before the creation of the first thread on FreeBSD 6")
1063 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
1064 'need signal.pthread_kill()')
1065 def test_pthread_kill_main_thread(self):
1066 # Test that a signal can be sent to the main thread with pthread_kill()
1067 # before any other thread has been created (see issue #12392).
1068 code = """if True:
1069 import threading
1070 import signal
1071 import sys
1072
1073 def handler(signum, frame):
1074 sys.exit(3)
1075
1076 signal.signal(signal.SIGUSR1, handler)
1077 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
1078 sys.exit(2)
1079 """
1080
1081 with spawn_python('-c', code) as process:
1082 stdout, stderr = process.communicate()
1083 exitcode = process.wait()
1084 if exitcode != 3:
1085 raise Exception("Child error (exit code %s): %s" %
1086 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +02001087
1088
Thomas Woutersed03b412007-08-28 21:37:11 +00001089def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +01001090 try:
Giampaolo Rodola'e09fb712014-04-04 15:34:17 +02001091 support.run_unittest(GenericTests, PosixTests, InterProcessSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -05001092 WakeupFDTests, WakeupSignalTests,
Victor Stinner11517102014-07-29 23:31:34 +02001093 WakeupSocketSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -05001094 SiginterruptTest, ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +02001095 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +01001096 finally:
1097 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +00001098
1099
1100if __name__ == "__main__":
1101 test_main()