blob: 74f74af0b469ed59f9c7b2da11766107abcdafcb [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002from test import support
Raymond Hettinger722d8c32009-06-18 22:21:03 +00003from contextlib import closing
Christian Heimescc47b052008-03-25 14:56:36 +00004import gc
Christian Heimes4fbc72b2008-03-22 00:47:35 +00005import pickle
6import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00007import signal
Victor Stinnerd49b1f12011-05-08 02:03:15 +02008import struct
Christian Heimes4fbc72b2008-03-22 00:47:35 +00009import subprocess
10import traceback
Christian Heimesc06950e2008-02-28 21:17:00 +000011import sys, os, time, errno
Victor Stinnerd6284962011-06-20 23:28:09 +020012from test.script_helper import assert_python_ok, spawn_python
Victor Stinnerb3e72192011-05-08 01:46:11 +020013try:
14 import threading
15except ImportError:
16 threading = None
Christian Heimesc06950e2008-02-28 21:17:00 +000017
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000018
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000019class HandlerBCalled(Exception):
20 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000021
Christian Heimes4fbc72b2008-03-22 00:47:35 +000022
23def exit_subprocess():
24 """Use os._exit(0) to exit the current subprocess.
25
26 Otherwise, the test catches the SystemExit and continues executing
27 in parallel with the original test, so you wind up with an
28 exponential number of tests running concurrently.
29 """
30 os._exit(0)
31
32
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000033def ignoring_eintr(__func, *args, **kwargs):
34 try:
35 return __func(*args, **kwargs)
Andrew Svetlov3438fa42012-12-17 23:35:18 +020036 except OSError as e:
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000037 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000038 raise
39 return None
40
41
Brian Curtin3f004b12010-08-06 19:34:52 +000042@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000043class InterProcessSignalTests(unittest.TestCase):
44 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000045
Christian Heimescc47b052008-03-25 14:56:36 +000046 def setUp(self):
47 self.using_gc = gc.isenabled()
48 gc.disable()
49
50 def tearDown(self):
51 if self.using_gc:
52 gc.enable()
53
Christian Heimes5e696852008-04-09 08:37:03 +000054 def format_frame(self, frame, limit=None):
55 return ''.join(traceback.format_stack(frame, limit=limit))
56
57 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000058 self.a_called = True
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000059
Christian Heimes5e696852008-04-09 08:37:03 +000060 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000061 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000062 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000063
Christian Heimes4fbc72b2008-03-22 00:47:35 +000064 def wait(self, child):
65 """Wait for child to finish, ignoring EINTR."""
66 while True:
67 try:
68 child.wait()
69 return
70 except OSError as e:
71 if e.errno != errno.EINTR:
72 raise
Fred Drake004d5e62000-10-23 17:22:08 +000073
Christian Heimes4fbc72b2008-03-22 00:47:35 +000074 def run_test(self):
75 # Install handlers. This function runs in a sub-process, so we
76 # don't worry about re-setting the default handlers.
77 signal.signal(signal.SIGHUP, self.handlerA)
78 signal.signal(signal.SIGUSR1, self.handlerB)
79 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
80 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000081
Christian Heimes4fbc72b2008-03-22 00:47:35 +000082 # Variables the signals will modify:
83 self.a_called = False
84 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000085
Christian Heimes4fbc72b2008-03-22 00:47:35 +000086 # Let the sub-processes know who to send signals to.
87 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000089 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
90 if child:
91 self.wait(child)
92 if not self.a_called:
93 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +000094 self.assertTrue(self.a_called)
95 self.assertFalse(self.b_called)
96 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000097
Christian Heimes5e696852008-04-09 08:37:03 +000098 # Make sure the signal isn't delivered while the previous
99 # Popen object is being destroyed, because __del__ swallows
100 # exceptions.
101 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000102 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000103 child = subprocess.Popen(['kill', '-USR1', str(pid)])
104 # This wait should be interrupted by the signal's exception.
105 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000106 time.sleep(1) # Give the signal time to be delivered.
Andrew Svetlov737fb892012-12-18 21:14:22 +0200107 self.fail('HandlerBCalled exception not raised')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000108 except HandlerBCalled:
109 self.assertTrue(self.b_called)
110 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000112 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
113 if child:
114 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000115
116 try:
117 signal.alarm(1)
118 # The race condition in pause doesn't matter in this case,
119 # since alarm is going to raise a KeyboardException, which
120 # will skip the call.
121 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000122 # But if another signal arrives before the alarm, pause
123 # may return early.
124 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000125 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200126 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000127 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000128 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000129 traceback.format_exc())
130 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000131 self.fail("pause returned of its own accord, and the signal"
132 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000133
R. David Murray44546f82010-04-21 01:59:28 +0000134 # Issue 3864, unknown if this affects earlier versions of freebsd also
135 @unittest.skipIf(sys.platform=='freebsd6',
136 'inter process signals not reliable (do not mix well with threading) '
137 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000138 def test_main(self):
139 # This function spawns a child process to insulate the main
140 # test-running process from all the signals. It then
141 # communicates with that child process over a pipe and
142 # re-raises information about any exceptions the child
Andrew Svetlov737fb892012-12-18 21:14:22 +0200143 # raises. The real work happens in self.run_test().
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000144 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000145 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
146 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000147 child = os.fork()
148 if child == 0:
149 # In the child process; run the test and report results
150 # through the pipe.
151 try:
152 done_r.close()
153 # Have to close done_w again here because
154 # exit_subprocess() will skip the enclosing with block.
155 with closing(done_w):
156 try:
157 self.run_test()
158 except:
159 pickle.dump(traceback.format_exc(), done_w)
160 else:
161 pickle.dump(None, done_w)
162 except:
163 print('Uh oh, raised from pickle.')
164 traceback.print_exc()
165 finally:
166 exit_subprocess()
167
168 done_w.close()
169 # Block for up to MAX_DURATION seconds for the test to finish.
170 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
171 if done_r in r:
172 tb = pickle.load(done_r)
173 if tb:
174 self.fail(tb)
175 else:
176 os.kill(child, signal.SIGKILL)
177 self.fail('Test deadlocked after %d seconds.' %
178 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000179
180
Brian Curtin3f004b12010-08-06 19:34:52 +0000181@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200182class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000183 def trivial_signal_handler(self, *args):
184 pass
185
Thomas Woutersed03b412007-08-28 21:37:11 +0000186 def test_out_of_range_signal_number_raises_error(self):
187 self.assertRaises(ValueError, signal.getsignal, 4242)
188
Thomas Woutersed03b412007-08-28 21:37:11 +0000189 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000190 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000191
192 def test_setting_signal_handler_to_none_raises_error(self):
193 self.assertRaises(TypeError, signal.signal,
194 signal.SIGUSR1, None)
195
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000196 def test_getsignal(self):
197 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000198 self.assertEqual(signal.getsignal(signal.SIGHUP),
199 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000200 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000201 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000202
203
Brian Curtin3f004b12010-08-06 19:34:52 +0000204@unittest.skipUnless(sys.platform == "win32", "Windows specific")
205class WindowsSignalTests(unittest.TestCase):
206 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000207 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000208 handler = lambda x, y: None
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000209 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +0000210 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
211 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
212 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000213 # Set and then reset a handler for signals that work on windows.
214 # Issue #18396, only for signals without a C-level handler.
215 if signal.getsignal(sig) is not None:
216 signal.signal(sig, signal.signal(sig, handler))
217 checked.add(sig)
218 # Issue #18396: Ensure the above loop at least tested *something*
219 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +0000220
221 with self.assertRaises(ValueError):
222 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000223
224 with self.assertRaises(ValueError):
225 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000226
227
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500228class WakeupFDTests(unittest.TestCase):
229
230 def test_invalid_fd(self):
231 fd = support.make_bad_fd()
232 self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
233
234
Brian Curtin3f004b12010-08-06 19:34:52 +0000235@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000236class WakeupSignalTests(unittest.TestCase):
Charles-François Natali027f9a32011-10-02 18:36:05 +0200237 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200238 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200239 code = """if 1:
240 import fcntl
241 import os
242 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200243 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000244
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200245 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200246
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200247 def handler(signum, frame):
248 pass
249
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200250 def check_signum(signals):
251 data = os.read(read, len(signals)+1)
252 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200253 if not {!r}:
254 raised = set(raised)
255 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200256 if raised != signals:
257 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200258
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200259 {}
260
261 signal.signal(signal.SIGALRM, handler)
262 read, write = os.pipe()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200263 for fd in (read, write):
264 flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
265 flags = flags | os.O_NONBLOCK
266 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200267 signal.set_wakeup_fd(write)
268
269 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200270 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200271
272 os.close(read)
273 os.close(write)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200274 """.format(signals, ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200275
276 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200277
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200278 def test_wakeup_write_error(self):
279 # Issue #16105: write() errors in the C signal handler should not
280 # pass silently.
281 # Use a subprocess to have only one thread.
282 code = """if 1:
283 import errno
284 import fcntl
285 import os
286 import signal
287 import sys
288 import time
289 from test.support import captured_stderr
290
291 def handler(signum, frame):
292 1/0
293
294 signal.signal(signal.SIGALRM, handler)
295 r, w = os.pipe()
296 flags = fcntl.fcntl(r, fcntl.F_GETFL, 0)
297 fcntl.fcntl(r, fcntl.F_SETFL, flags | os.O_NONBLOCK)
298
299 # Set wakeup_fd a read-only file descriptor to trigger the error
300 signal.set_wakeup_fd(r)
301 try:
302 with captured_stderr() as err:
303 signal.alarm(1)
304 time.sleep(5.0)
305 except ZeroDivisionError:
306 # An ignored exception should have been printed out on stderr
307 err = err.getvalue()
308 if ('Exception ignored when trying to write to the signal wakeup fd'
309 not in err):
310 raise AssertionError(err)
311 if ('OSError: [Errno %d]' % errno.EBADF) not in err:
312 raise AssertionError(err)
313 else:
314 raise AssertionError("ZeroDivisionError not raised")
315 """
Antoine Pitrou8f0bdda2013-08-17 21:43:47 +0200316 r, w = os.pipe()
317 try:
318 os.write(r, b'x')
319 except OSError:
320 pass
321 else:
322 self.skipTest("OS doesn't report write() error on the read end of a pipe")
323 finally:
324 os.close(r)
325 os.close(w)
Antoine Pitrou6f6ec372013-08-17 20:27:56 +0200326
327 assert_python_ok('-c', code)
328
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000329 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200330 self.check_wakeup("""def test():
331 import select
332 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000333
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200334 TIMEOUT_FULL = 10
335 TIMEOUT_HALF = 5
336
337 signal.alarm(1)
338 before_time = time.time()
339 # We attempt to get a signal during the sleep,
340 # before select is called
341 time.sleep(TIMEOUT_FULL)
342 mid_time = time.time()
343 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200344 if dt >= TIMEOUT_HALF:
345 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200346 select.select([read], [], [], TIMEOUT_FULL)
347 after_time = time.time()
348 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200349 if dt >= TIMEOUT_HALF:
350 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200351 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000352
353 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200354 self.check_wakeup("""def test():
355 import select
356 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000357
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200358 TIMEOUT_FULL = 10
359 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000360
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200361 signal.alarm(1)
362 before_time = time.time()
363 # We attempt to get a signal during the select call
364 try:
365 select.select([read], [], [], TIMEOUT_FULL)
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200366 except OSError:
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200367 pass
368 else:
Andrew Svetlov6d8a1222012-12-17 22:23:46 +0200369 raise Exception("OSError not raised")
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200370 after_time = time.time()
371 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200372 if dt >= TIMEOUT_HALF:
373 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200374 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200375
376 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200377 self.check_wakeup("""def test():
378 signal.signal(signal.SIGUSR1, handler)
379 os.kill(os.getpid(), signal.SIGUSR1)
380 os.kill(os.getpid(), signal.SIGALRM)
381 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000382
Victor Stinnerc13ef662011-05-25 02:35:58 +0200383 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
384 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200385 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200386 self.check_wakeup("""def test():
387 signum1 = signal.SIGUSR1
388 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200389
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200390 signal.signal(signum1, handler)
391 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200392
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200393 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
394 os.kill(os.getpid(), signum1)
395 os.kill(os.getpid(), signum2)
396 # Unblocking the 2 signals calls the C signal handler twice
397 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200398 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200399
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000400
Brian Curtin3f004b12010-08-06 19:34:52 +0000401@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000402class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000403
Victor Stinnerd6284962011-06-20 23:28:09 +0200404 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000405 """Perform a read during which a signal will arrive. Return True if the
406 read is interrupted by the signal and raises an exception. Return False
407 if it returns normally.
408 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200409 # use a subprocess to have only one thread, to have a timeout on the
410 # blocking read and to not touch signal handling in this process
411 code = """if 1:
412 import errno
413 import os
414 import signal
415 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000416
Victor Stinnerd6284962011-06-20 23:28:09 +0200417 interrupt = %r
418 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000419
Victor Stinnerd6284962011-06-20 23:28:09 +0200420 def handler(signum, frame):
421 pass
422
423 signal.signal(signal.SIGALRM, handler)
424 if interrupt is not None:
425 signal.siginterrupt(signal.SIGALRM, interrupt)
426
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200427 print("ready")
428 sys.stdout.flush()
429
Victor Stinnerd6284962011-06-20 23:28:09 +0200430 # run the test twice
431 for loop in range(2):
432 # send a SIGALRM in a second (during the read)
433 signal.alarm(1)
434 try:
435 # blocking call: read from a pipe without data
436 os.read(r, 1)
437 except OSError as err:
438 if err.errno != errno.EINTR:
439 raise
440 else:
441 sys.exit(2)
442 sys.exit(3)
443 """ % (interrupt,)
444 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000445 try:
Victor Stinner45273652011-06-22 22:15:51 +0200446 # wait until the child process is loaded and has started
447 first_line = process.stdout.readline()
448
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200449 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200450 except subprocess.TimeoutExpired:
451 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000452 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200453 else:
Victor Stinner45273652011-06-22 22:15:51 +0200454 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200455 exitcode = process.wait()
456 if exitcode not in (2, 3):
Antoine Pitroudab4e8a2014-05-11 19:05:23 +0200457 raise Exception("Child error (exit code %s): %r"
Victor Stinnerd6284962011-06-20 23:28:09 +0200458 % (exitcode, stdout))
459 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000460
461 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200462 # If a signal handler is installed and siginterrupt is not called
463 # at all, when that signal arrives, it interrupts a syscall that's in
464 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200465 interrupted = self.readpipe_interrupted(None)
466 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000467
468 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200469 # If a signal handler is installed and siginterrupt is called with
470 # a true value for the second argument, when that signal arrives, it
471 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200472 interrupted = self.readpipe_interrupted(True)
473 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000474
475 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200476 # If a signal handler is installed and siginterrupt is called with
477 # a false value for the second argument, when that signal arrives, it
478 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200479 interrupted = self.readpipe_interrupted(False)
480 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000481
482
Brian Curtin3f004b12010-08-06 19:34:52 +0000483@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000484class ItimerTest(unittest.TestCase):
485 def setUp(self):
486 self.hndl_called = False
487 self.hndl_count = 0
488 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000489 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000490
491 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000492 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000493 if self.itimer is not None: # test_itimer_exc doesn't change this attr
494 # just ensure that itimer is stopped
495 signal.setitimer(self.itimer, 0)
496
497 def sig_alrm(self, *args):
498 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000499
500 def sig_vtalrm(self, *args):
501 self.hndl_called = True
502
503 if self.hndl_count > 3:
504 # it shouldn't be here, because it should have been disabled.
505 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
506 "timer.")
507 elif self.hndl_count == 3:
508 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
509 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000510
511 self.hndl_count += 1
512
Martin v. Löwis823725e2008-03-24 13:39:54 +0000513 def sig_prof(self, *args):
514 self.hndl_called = True
515 signal.setitimer(signal.ITIMER_PROF, 0)
516
Martin v. Löwis823725e2008-03-24 13:39:54 +0000517 def test_itimer_exc(self):
518 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
519 # defines it ?
520 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000521 # Negative times are treated as zero on some platforms.
522 if 0:
523 self.assertRaises(signal.ItimerError,
524 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000525
526 def test_itimer_real(self):
527 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000528 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000529 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000530 self.assertEqual(self.hndl_called, True)
531
R. David Murray44546f82010-04-21 01:59:28 +0000532 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000533 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
534 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000535 def test_itimer_virtual(self):
536 self.itimer = signal.ITIMER_VIRTUAL
537 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
538 signal.setitimer(self.itimer, 0.3, 0.2)
539
Mark Dickinson78373472009-10-31 10:39:21 +0000540 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000541 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000542 # use up some virtual time by doing real work
543 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000544 if signal.getitimer(self.itimer) == (0.0, 0.0):
545 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000546 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000547 self.skipTest("timeout: likely cause: machine too slow or load too "
548 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000549
550 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000551 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000552 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000553 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000554
R. David Murray44546f82010-04-21 01:59:28 +0000555 # Issue 3864, unknown if this affects earlier versions of freebsd also
556 @unittest.skipIf(sys.platform=='freebsd6',
557 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000558 def test_itimer_prof(self):
559 self.itimer = signal.ITIMER_PROF
560 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000561 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000562
Mark Dickinson78373472009-10-31 10:39:21 +0000563 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000564 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000565 # do some work
566 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000567 if signal.getitimer(self.itimer) == (0.0, 0.0):
568 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000569 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000570 self.skipTest("timeout: likely cause: machine too slow or load too "
571 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000572
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000573 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000574 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000575 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000576 self.assertEqual(self.hndl_called, True)
577
Victor Stinnera9293352011-04-30 15:21:58 +0200578
Victor Stinner35b300c2011-05-04 13:20:35 +0200579class PendingSignalsTests(unittest.TestCase):
580 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200581 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
582 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200583 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200584 @unittest.skipUnless(hasattr(signal, 'sigpending'),
585 'need signal.sigpending()')
586 def test_sigpending_empty(self):
587 self.assertEqual(signal.sigpending(), set())
588
589 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
590 'need signal.pthread_sigmask()')
591 @unittest.skipUnless(hasattr(signal, 'sigpending'),
592 'need signal.sigpending()')
593 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200594 code = """if 1:
595 import os
596 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200597
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200598 def handler(signum, frame):
599 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200600
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200601 signum = signal.SIGUSR1
602 signal.signal(signum, handler)
603
604 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
605 os.kill(os.getpid(), signum)
606 pending = signal.sigpending()
Victor Stinner0a01f132011-07-04 18:06:35 +0200607 if pending != {signum}:
608 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200609 try:
610 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
611 except ZeroDivisionError:
612 pass
613 else:
614 raise Exception("ZeroDivisionError not raised")
615 """
616 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200617
618 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
619 'need signal.pthread_kill()')
620 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200621 code = """if 1:
622 import signal
623 import threading
624 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200625
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200626 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200627
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200628 def handler(signum, frame):
629 1/0
630
631 signal.signal(signum, handler)
632
633 if sys.platform == 'freebsd6':
634 # Issue #12392 and #12469: send a signal to the main thread
635 # doesn't work before the creation of the first thread on
636 # FreeBSD 6
637 def noop():
638 pass
639 thread = threading.Thread(target=noop)
640 thread.start()
641 thread.join()
642
643 tid = threading.get_ident()
644 try:
645 signal.pthread_kill(tid, signum)
646 except ZeroDivisionError:
647 pass
648 else:
649 raise Exception("ZeroDivisionError not raised")
650 """
651 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200652
Victor Stinner7f294d12011-06-10 14:02:10 +0200653 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
654 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200655 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200656 """
657 test: body of the "def test(signum):" function.
658 blocked: number of the blocked signal
659 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200660 code = '''if 1:
661 import signal
662 import sys
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200663
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200664 def handler(signum, frame):
665 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200666
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200667 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200668
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200669 blocked = %s
670 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200671
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200672 # child: block and wait the signal
673 try:
674 signal.signal(signum, handler)
675 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200676
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200677 # Do the tests
678 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200679
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200680 # The handler must not be called on unblock
681 try:
682 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
683 except ZeroDivisionError:
684 print("the signal handler has been called",
685 file=sys.stderr)
686 sys.exit(1)
687 except BaseException as err:
688 print("error: {}".format(err), file=sys.stderr)
689 sys.stderr.flush()
690 sys.exit(1)
691 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200692
Ross Lagerwallbc808222011-06-25 12:13:40 +0200693 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200694 # process might have several threads running, use a subprocess to have
695 # a single thread.
696 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200697
Victor Stinnerb3e72192011-05-08 01:46:11 +0200698 @unittest.skipUnless(hasattr(signal, 'sigwait'),
699 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200700 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200701 self.wait_helper(signal.SIGALRM, '''
702 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200703 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200704 received = signal.sigwait([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200705 if received != signum:
706 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200707 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200708
709 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
710 'need signal.sigwaitinfo()')
711 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200712 self.wait_helper(signal.SIGALRM, '''
713 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200714 signal.alarm(1)
715 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200716 if info.si_signo != signum:
717 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200718 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200719
720 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
721 'need signal.sigtimedwait()')
722 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200723 self.wait_helper(signal.SIGALRM, '''
724 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200725 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100726 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200727 if info.si_signo != signum:
728 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200729 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200730
Ross Lagerwallbc808222011-06-25 12:13:40 +0200731 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
732 'need signal.sigtimedwait()')
733 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200734 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200735 self.wait_helper(signal.SIGALRM, '''
736 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200737 import os
738 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100739 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200740 if info.si_signo != signum:
741 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200742 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200743
744 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
745 'need signal.sigtimedwait()')
746 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200747 self.wait_helper(signal.SIGALRM, '''
748 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100749 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200750 if received is not None:
751 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200752 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200753
754 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
755 'need signal.sigtimedwait()')
756 def test_sigtimedwait_negative_timeout(self):
757 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100758 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200759
Ross Lagerwallbc808222011-06-25 12:13:40 +0200760 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
761 'need signal.sigwaitinfo()')
Victor Stinner91f9bdd2013-06-17 21:51:56 +0200762 # Issue #18238: sigwaitinfo() can be interrupted on Linux (raises
763 # InterruptedError), but not on AIX
764 @unittest.skipIf(sys.platform.startswith("aix"),
765 'signal.sigwaitinfo() cannot be interrupted on AIX')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200766 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200767 self.wait_helper(signal.SIGUSR1, '''
768 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200769 import errno
770
771 hndl_called = True
772 def alarm_handler(signum, frame):
773 hndl_called = False
774
775 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200776 signal.alarm(1)
777 try:
778 signal.sigwaitinfo([signal.SIGUSR1])
779 except OSError as e:
780 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200781 if not hndl_called:
782 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200783 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200784 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200785 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200786 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200787 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200788
789 @unittest.skipUnless(hasattr(signal, 'sigwait'),
790 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200791 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
792 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200793 @unittest.skipIf(threading is None, "test needs threading module")
794 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200795 # Check that calling sigwait() from a thread doesn't suspend the whole
796 # process. A new interpreter is spawned to avoid problems when mixing
797 # threads and fork(): only async-safe functions are allowed between
798 # fork() and exec().
799 assert_python_ok("-c", """if True:
800 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200801
Victor Stinner415007e2011-06-13 16:19:06 +0200802 # the default handler terminates the process
803 signum = signal.SIGUSR1
804
805 def kill_later():
806 # wait until the main thread is waiting in sigwait()
807 time.sleep(1)
808 os.kill(os.getpid(), signum)
809
810 # the signal must be blocked by all the threads
811 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
812 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200813 killer.start()
814 received = signal.sigwait([signum])
815 if received != signum:
816 print("sigwait() received %s, not %s" % (received, signum),
817 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200818 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200819 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200820 # unblock the signal, which should have been cleared by sigwait()
821 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
822 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200823
Victor Stinnerb3e72192011-05-08 01:46:11 +0200824 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
825 'need signal.pthread_sigmask()')
826 def test_pthread_sigmask_arguments(self):
827 self.assertRaises(TypeError, signal.pthread_sigmask)
828 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
829 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
830 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
831
832 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
833 'need signal.pthread_sigmask()')
834 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200835 code = """if 1:
836 import signal
837 import os; import threading
838
839 def handler(signum, frame):
840 1/0
841
842 def kill(signum):
843 os.kill(os.getpid(), signum)
844
845 def read_sigmask():
846 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
847
Victor Stinnerb3e72192011-05-08 01:46:11 +0200848 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200849
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200850 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200851 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200852
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200853 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200854 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200855 try:
856 kill(signum)
857 except ZeroDivisionError:
858 pass
859 else:
860 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200861
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200862 # Block and then raise SIGUSR1. The signal is blocked: the signal
863 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200864 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200865 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200866
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200867 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200868 blocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200869 if signum not in blocked:
870 raise Exception("%s not in %s" % (signum, blocked))
871 if old_mask ^ blocked != {signum}:
872 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200873
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200874 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200875 try:
R David Murrayfc069992013-12-13 20:52:19 -0500876 # unblock the pending signal calls immediately the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200877 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200878 except ZeroDivisionError:
879 pass
880 else:
881 raise Exception("ZeroDivisionError not raised")
882 try:
883 kill(signum)
884 except ZeroDivisionError:
885 pass
886 else:
887 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200888
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200889 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200890 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200891 if signum in unblocked:
892 raise Exception("%s in %s" % (signum, unblocked))
893 if blocked ^ unblocked != {signum}:
894 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
895 if old_mask != unblocked:
896 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200897 """
898 assert_python_ok('-c', code)
899
900 @unittest.skipIf(sys.platform == 'freebsd6',
901 "issue #12392: send a signal to the main thread doesn't work "
902 "before the creation of the first thread on FreeBSD 6")
903 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
904 'need signal.pthread_kill()')
905 def test_pthread_kill_main_thread(self):
906 # Test that a signal can be sent to the main thread with pthread_kill()
907 # before any other thread has been created (see issue #12392).
908 code = """if True:
909 import threading
910 import signal
911 import sys
912
913 def handler(signum, frame):
914 sys.exit(3)
915
916 signal.signal(signal.SIGUSR1, handler)
917 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
918 sys.exit(2)
919 """
920
921 with spawn_python('-c', code) as process:
922 stdout, stderr = process.communicate()
923 exitcode = process.wait()
924 if exitcode != 3:
925 raise Exception("Child error (exit code %s): %s" %
926 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200927
928
Thomas Woutersed03b412007-08-28 21:37:11 +0000929def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100930 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200931 support.run_unittest(PosixTests, InterProcessSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500932 WakeupFDTests, WakeupSignalTests,
933 SiginterruptTest, ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200934 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100935 finally:
936 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000937
938
939if __name__ == "__main__":
940 test_main()