blob: 99243dffe104ab8c7829f8eff7b834c047fa9b7f [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
Brian Curtin912443c2010-09-06 16:10:04 +000018if sys.platform in ('os2', 'riscos'):
19 raise unittest.SkipTest("Can't test signal on %s" % sys.platform)
Christian Heimesc06950e2008-02-28 21:17:00 +000020
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000021
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000022class HandlerBCalled(Exception):
23 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000024
Christian Heimes4fbc72b2008-03-22 00:47:35 +000025
26def exit_subprocess():
27 """Use os._exit(0) to exit the current subprocess.
28
29 Otherwise, the test catches the SystemExit and continues executing
30 in parallel with the original test, so you wind up with an
31 exponential number of tests running concurrently.
32 """
33 os._exit(0)
34
35
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000036def ignoring_eintr(__func, *args, **kwargs):
37 try:
38 return __func(*args, **kwargs)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000039 except EnvironmentError as e:
40 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000041 raise
42 return None
43
44
Brian Curtin3f004b12010-08-06 19:34:52 +000045@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000046class InterProcessSignalTests(unittest.TestCase):
47 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000048
Christian Heimescc47b052008-03-25 14:56:36 +000049 def setUp(self):
50 self.using_gc = gc.isenabled()
51 gc.disable()
52
53 def tearDown(self):
54 if self.using_gc:
55 gc.enable()
56
Christian Heimes5e696852008-04-09 08:37:03 +000057 def format_frame(self, frame, limit=None):
58 return ''.join(traceback.format_stack(frame, limit=limit))
59
60 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000061 self.a_called = True
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000062
Christian Heimes5e696852008-04-09 08:37:03 +000063 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000064 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000065 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000066
Christian Heimes4fbc72b2008-03-22 00:47:35 +000067 def wait(self, child):
68 """Wait for child to finish, ignoring EINTR."""
69 while True:
70 try:
71 child.wait()
72 return
73 except OSError as e:
74 if e.errno != errno.EINTR:
75 raise
Fred Drake004d5e62000-10-23 17:22:08 +000076
Christian Heimes4fbc72b2008-03-22 00:47:35 +000077 def run_test(self):
78 # Install handlers. This function runs in a sub-process, so we
79 # don't worry about re-setting the default handlers.
80 signal.signal(signal.SIGHUP, self.handlerA)
81 signal.signal(signal.SIGUSR1, self.handlerB)
82 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
83 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000084
Christian Heimes4fbc72b2008-03-22 00:47:35 +000085 # Variables the signals will modify:
86 self.a_called = False
87 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088
Christian Heimes4fbc72b2008-03-22 00:47:35 +000089 # Let the sub-processes know who to send signals to.
90 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000091
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000092 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
93 if child:
94 self.wait(child)
95 if not self.a_called:
96 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +000097 self.assertTrue(self.a_called)
98 self.assertFalse(self.b_called)
99 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000100
Christian Heimes5e696852008-04-09 08:37:03 +0000101 # Make sure the signal isn't delivered while the previous
102 # Popen object is being destroyed, because __del__ swallows
103 # exceptions.
104 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000106 child = subprocess.Popen(['kill', '-USR1', str(pid)])
107 # This wait should be interrupted by the signal's exception.
108 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000109 time.sleep(1) # Give the signal time to be delivered.
Andrew Svetlov737fb892012-12-18 21:14:22 +0200110 self.fail('HandlerBCalled exception not raised')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000111 except HandlerBCalled:
112 self.assertTrue(self.b_called)
113 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000115 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
116 if child:
117 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000118
119 try:
120 signal.alarm(1)
121 # The race condition in pause doesn't matter in this case,
122 # since alarm is going to raise a KeyboardException, which
123 # will skip the call.
124 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000125 # But if another signal arrives before the alarm, pause
126 # may return early.
127 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000128 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200129 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000130 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000131 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000132 traceback.format_exc())
133 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000134 self.fail("pause returned of its own accord, and the signal"
135 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
R. David Murray44546f82010-04-21 01:59:28 +0000137 # Issue 3864, unknown if this affects earlier versions of freebsd also
138 @unittest.skipIf(sys.platform=='freebsd6',
139 'inter process signals not reliable (do not mix well with threading) '
140 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000141 def test_main(self):
142 # This function spawns a child process to insulate the main
143 # test-running process from all the signals. It then
144 # communicates with that child process over a pipe and
145 # re-raises information about any exceptions the child
Andrew Svetlov737fb892012-12-18 21:14:22 +0200146 # raises. The real work happens in self.run_test().
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000147 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000148 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
149 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000150 child = os.fork()
151 if child == 0:
152 # In the child process; run the test and report results
153 # through the pipe.
154 try:
155 done_r.close()
156 # Have to close done_w again here because
157 # exit_subprocess() will skip the enclosing with block.
158 with closing(done_w):
159 try:
160 self.run_test()
161 except:
162 pickle.dump(traceback.format_exc(), done_w)
163 else:
164 pickle.dump(None, done_w)
165 except:
166 print('Uh oh, raised from pickle.')
167 traceback.print_exc()
168 finally:
169 exit_subprocess()
170
171 done_w.close()
172 # Block for up to MAX_DURATION seconds for the test to finish.
173 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
174 if done_r in r:
175 tb = pickle.load(done_r)
176 if tb:
177 self.fail(tb)
178 else:
179 os.kill(child, signal.SIGKILL)
180 self.fail('Test deadlocked after %d seconds.' %
181 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000182
183
Brian Curtin3f004b12010-08-06 19:34:52 +0000184@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200185class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000186 def trivial_signal_handler(self, *args):
187 pass
188
Thomas Woutersed03b412007-08-28 21:37:11 +0000189 def test_out_of_range_signal_number_raises_error(self):
190 self.assertRaises(ValueError, signal.getsignal, 4242)
191
Thomas Woutersed03b412007-08-28 21:37:11 +0000192 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000193 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000194
195 def test_setting_signal_handler_to_none_raises_error(self):
196 self.assertRaises(TypeError, signal.signal,
197 signal.SIGUSR1, None)
198
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000199 def test_getsignal(self):
200 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000201 self.assertEqual(signal.getsignal(signal.SIGHUP),
202 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000203 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000204 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000205
206
Brian Curtin3f004b12010-08-06 19:34:52 +0000207@unittest.skipUnless(sys.platform == "win32", "Windows specific")
208class WindowsSignalTests(unittest.TestCase):
209 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000210 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000211 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +0000212 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
213 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
214 signal.SIGTERM):
215 # Set and then reset a handler for signals that work on windows
216 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin3f004b12010-08-06 19:34:52 +0000217
218 with self.assertRaises(ValueError):
219 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000220
221 with self.assertRaises(ValueError):
222 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000223
224
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500225class WakeupFDTests(unittest.TestCase):
226
227 def test_invalid_fd(self):
228 fd = support.make_bad_fd()
229 self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
230
231
Brian Curtin3f004b12010-08-06 19:34:52 +0000232@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000233class WakeupSignalTests(unittest.TestCase):
Charles-François Natali027f9a32011-10-02 18:36:05 +0200234 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200235 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200236 code = """if 1:
237 import fcntl
238 import os
239 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200240 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000241
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200242 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200243
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200244 def handler(signum, frame):
245 pass
246
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200247 def check_signum(signals):
248 data = os.read(read, len(signals)+1)
249 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200250 if not {!r}:
251 raised = set(raised)
252 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200253 if raised != signals:
254 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200255
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200256 {}
257
258 signal.signal(signal.SIGALRM, handler)
259 read, write = os.pipe()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200260 for fd in (read, write):
261 flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
262 flags = flags | os.O_NONBLOCK
263 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200264 signal.set_wakeup_fd(write)
265
266 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200267 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200268
269 os.close(read)
270 os.close(write)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200271 """.format(signals, ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200272
273 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200274
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000275 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200276 self.check_wakeup("""def test():
277 import select
278 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000279
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200280 TIMEOUT_FULL = 10
281 TIMEOUT_HALF = 5
282
283 signal.alarm(1)
284 before_time = time.time()
285 # We attempt to get a signal during the sleep,
286 # before select is called
287 time.sleep(TIMEOUT_FULL)
288 mid_time = time.time()
289 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200290 if dt >= TIMEOUT_HALF:
291 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200292 select.select([read], [], [], TIMEOUT_FULL)
293 after_time = time.time()
294 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200295 if dt >= TIMEOUT_HALF:
296 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200297 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000298
299 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200300 self.check_wakeup("""def test():
301 import select
302 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000303
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200304 TIMEOUT_FULL = 10
305 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000306
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200307 signal.alarm(1)
308 before_time = time.time()
309 # We attempt to get a signal during the select call
310 try:
311 select.select([read], [], [], TIMEOUT_FULL)
312 except select.error:
313 pass
314 else:
315 raise Exception("select.error not raised")
316 after_time = time.time()
317 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200318 if dt >= TIMEOUT_HALF:
319 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200320 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200321
322 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200323 self.check_wakeup("""def test():
324 signal.signal(signal.SIGUSR1, handler)
325 os.kill(os.getpid(), signal.SIGUSR1)
326 os.kill(os.getpid(), signal.SIGALRM)
327 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000328
Victor Stinnerc13ef662011-05-25 02:35:58 +0200329 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
330 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200331 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200332 self.check_wakeup("""def test():
333 signum1 = signal.SIGUSR1
334 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200335
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200336 signal.signal(signum1, handler)
337 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200338
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200339 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
340 os.kill(os.getpid(), signum1)
341 os.kill(os.getpid(), signum2)
342 # Unblocking the 2 signals calls the C signal handler twice
343 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200344 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200345
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000346
Brian Curtin3f004b12010-08-06 19:34:52 +0000347@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000348class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000349
Victor Stinnerd6284962011-06-20 23:28:09 +0200350 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000351 """Perform a read during which a signal will arrive. Return True if the
352 read is interrupted by the signal and raises an exception. Return False
353 if it returns normally.
354 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200355 # use a subprocess to have only one thread, to have a timeout on the
356 # blocking read and to not touch signal handling in this process
357 code = """if 1:
358 import errno
359 import os
360 import signal
361 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000362
Victor Stinnerd6284962011-06-20 23:28:09 +0200363 interrupt = %r
364 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000365
Victor Stinnerd6284962011-06-20 23:28:09 +0200366 def handler(signum, frame):
367 pass
368
369 signal.signal(signal.SIGALRM, handler)
370 if interrupt is not None:
371 signal.siginterrupt(signal.SIGALRM, interrupt)
372
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200373 print("ready")
374 sys.stdout.flush()
375
Victor Stinnerd6284962011-06-20 23:28:09 +0200376 # run the test twice
377 for loop in range(2):
378 # send a SIGALRM in a second (during the read)
379 signal.alarm(1)
380 try:
381 # blocking call: read from a pipe without data
382 os.read(r, 1)
383 except OSError as err:
384 if err.errno != errno.EINTR:
385 raise
386 else:
387 sys.exit(2)
388 sys.exit(3)
389 """ % (interrupt,)
390 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000391 try:
Victor Stinner45273652011-06-22 22:15:51 +0200392 # wait until the child process is loaded and has started
393 first_line = process.stdout.readline()
394
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200395 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200396 except subprocess.TimeoutExpired:
397 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000398 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200399 else:
Victor Stinner45273652011-06-22 22:15:51 +0200400 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200401 exitcode = process.wait()
402 if exitcode not in (2, 3):
403 raise Exception("Child error (exit code %s): %s"
404 % (exitcode, stdout))
405 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000406
407 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200408 # If a signal handler is installed and siginterrupt is not called
409 # at all, when that signal arrives, it interrupts a syscall that's in
410 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200411 interrupted = self.readpipe_interrupted(None)
412 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000413
414 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200415 # If a signal handler is installed and siginterrupt is called with
416 # a true value for the second argument, when that signal arrives, it
417 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200418 interrupted = self.readpipe_interrupted(True)
419 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000420
421 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200422 # If a signal handler is installed and siginterrupt is called with
423 # a false value for the second argument, when that signal arrives, it
424 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200425 interrupted = self.readpipe_interrupted(False)
426 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000427
428
Brian Curtin3f004b12010-08-06 19:34:52 +0000429@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000430class ItimerTest(unittest.TestCase):
431 def setUp(self):
432 self.hndl_called = False
433 self.hndl_count = 0
434 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000435 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000436
437 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000438 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000439 if self.itimer is not None: # test_itimer_exc doesn't change this attr
440 # just ensure that itimer is stopped
441 signal.setitimer(self.itimer, 0)
442
443 def sig_alrm(self, *args):
444 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000445
446 def sig_vtalrm(self, *args):
447 self.hndl_called = True
448
449 if self.hndl_count > 3:
450 # it shouldn't be here, because it should have been disabled.
451 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
452 "timer.")
453 elif self.hndl_count == 3:
454 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
455 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000456
457 self.hndl_count += 1
458
Martin v. Löwis823725e2008-03-24 13:39:54 +0000459 def sig_prof(self, *args):
460 self.hndl_called = True
461 signal.setitimer(signal.ITIMER_PROF, 0)
462
Martin v. Löwis823725e2008-03-24 13:39:54 +0000463 def test_itimer_exc(self):
464 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
465 # defines it ?
466 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000467 # Negative times are treated as zero on some platforms.
468 if 0:
469 self.assertRaises(signal.ItimerError,
470 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000471
472 def test_itimer_real(self):
473 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000474 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000475 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000476 self.assertEqual(self.hndl_called, True)
477
R. David Murray44546f82010-04-21 01:59:28 +0000478 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000479 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
480 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000481 def test_itimer_virtual(self):
482 self.itimer = signal.ITIMER_VIRTUAL
483 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
484 signal.setitimer(self.itimer, 0.3, 0.2)
485
Mark Dickinson78373472009-10-31 10:39:21 +0000486 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000487 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000488 # use up some virtual time by doing real work
489 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000490 if signal.getitimer(self.itimer) == (0.0, 0.0):
491 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000492 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000493 self.skipTest("timeout: likely cause: machine too slow or load too "
494 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000495
496 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000497 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000498 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000499 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000500
R. David Murray44546f82010-04-21 01:59:28 +0000501 # Issue 3864, unknown if this affects earlier versions of freebsd also
502 @unittest.skipIf(sys.platform=='freebsd6',
503 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000504 def test_itimer_prof(self):
505 self.itimer = signal.ITIMER_PROF
506 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000507 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000508
Mark Dickinson78373472009-10-31 10:39:21 +0000509 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000510 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000511 # do some work
512 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000513 if signal.getitimer(self.itimer) == (0.0, 0.0):
514 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000515 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000516 self.skipTest("timeout: likely cause: machine too slow or load too "
517 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000518
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000519 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000520 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000521 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000522 self.assertEqual(self.hndl_called, True)
523
Victor Stinnera9293352011-04-30 15:21:58 +0200524
Victor Stinner35b300c2011-05-04 13:20:35 +0200525class PendingSignalsTests(unittest.TestCase):
526 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200527 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
528 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200529 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200530 @unittest.skipUnless(hasattr(signal, 'sigpending'),
531 'need signal.sigpending()')
532 def test_sigpending_empty(self):
533 self.assertEqual(signal.sigpending(), set())
534
535 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
536 'need signal.pthread_sigmask()')
537 @unittest.skipUnless(hasattr(signal, 'sigpending'),
538 'need signal.sigpending()')
539 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200540 code = """if 1:
541 import os
542 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200543
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200544 def handler(signum, frame):
545 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200546
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200547 signum = signal.SIGUSR1
548 signal.signal(signum, handler)
549
550 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
551 os.kill(os.getpid(), signum)
552 pending = signal.sigpending()
Victor Stinner0a01f132011-07-04 18:06:35 +0200553 if pending != {signum}:
554 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200555 try:
556 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
557 except ZeroDivisionError:
558 pass
559 else:
560 raise Exception("ZeroDivisionError not raised")
561 """
562 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200563
564 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
565 'need signal.pthread_kill()')
566 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200567 code = """if 1:
568 import signal
569 import threading
570 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200571
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200572 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200573
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200574 def handler(signum, frame):
575 1/0
576
577 signal.signal(signum, handler)
578
579 if sys.platform == 'freebsd6':
580 # Issue #12392 and #12469: send a signal to the main thread
581 # doesn't work before the creation of the first thread on
582 # FreeBSD 6
583 def noop():
584 pass
585 thread = threading.Thread(target=noop)
586 thread.start()
587 thread.join()
588
589 tid = threading.get_ident()
590 try:
591 signal.pthread_kill(tid, signum)
592 except ZeroDivisionError:
593 pass
594 else:
595 raise Exception("ZeroDivisionError not raised")
596 """
597 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200598
Victor Stinner7f294d12011-06-10 14:02:10 +0200599 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
600 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200601 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200602 """
603 test: body of the "def test(signum):" function.
604 blocked: number of the blocked signal
605 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200606 code = '''if 1:
607 import signal
608 import sys
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200609
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200610 def handler(signum, frame):
611 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200612
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200613 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200614
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200615 blocked = %s
616 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200617
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200618 # child: block and wait the signal
619 try:
620 signal.signal(signum, handler)
621 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200622
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200623 # Do the tests
624 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200625
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200626 # The handler must not be called on unblock
627 try:
628 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
629 except ZeroDivisionError:
630 print("the signal handler has been called",
631 file=sys.stderr)
632 sys.exit(1)
633 except BaseException as err:
634 print("error: {}".format(err), file=sys.stderr)
635 sys.stderr.flush()
636 sys.exit(1)
637 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200638
Ross Lagerwallbc808222011-06-25 12:13:40 +0200639 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200640 # process might have several threads running, use a subprocess to have
641 # a single thread.
642 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200643
Victor Stinnerb3e72192011-05-08 01:46:11 +0200644 @unittest.skipUnless(hasattr(signal, 'sigwait'),
645 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200646 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200647 self.wait_helper(signal.SIGALRM, '''
648 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200649 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200650 received = signal.sigwait([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200651 if received != signum:
652 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200653 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200654
655 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
656 'need signal.sigwaitinfo()')
657 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200658 self.wait_helper(signal.SIGALRM, '''
659 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200660 signal.alarm(1)
661 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200662 if info.si_signo != signum:
663 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200664 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200665
666 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
667 'need signal.sigtimedwait()')
668 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200669 self.wait_helper(signal.SIGALRM, '''
670 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200671 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100672 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200673 if info.si_signo != signum:
674 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200675 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200676
Ross Lagerwallbc808222011-06-25 12:13:40 +0200677 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
678 'need signal.sigtimedwait()')
679 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200680 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200681 self.wait_helper(signal.SIGALRM, '''
682 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200683 import os
684 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100685 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200686 if info.si_signo != signum:
687 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200688 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200689
690 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
691 'need signal.sigtimedwait()')
692 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200693 self.wait_helper(signal.SIGALRM, '''
694 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100695 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200696 if received is not None:
697 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200698 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200699
700 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
701 'need signal.sigtimedwait()')
702 def test_sigtimedwait_negative_timeout(self):
703 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100704 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200705
Ross Lagerwallbc808222011-06-25 12:13:40 +0200706 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
707 'need signal.sigwaitinfo()')
708 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200709 self.wait_helper(signal.SIGUSR1, '''
710 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200711 import errno
712
713 hndl_called = True
714 def alarm_handler(signum, frame):
715 hndl_called = False
716
717 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200718 signal.alarm(1)
719 try:
720 signal.sigwaitinfo([signal.SIGUSR1])
721 except OSError as e:
722 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200723 if not hndl_called:
724 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200725 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200726 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200727 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200728 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200729 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200730
731 @unittest.skipUnless(hasattr(signal, 'sigwait'),
732 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200733 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
734 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200735 @unittest.skipIf(threading is None, "test needs threading module")
736 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200737 # Check that calling sigwait() from a thread doesn't suspend the whole
738 # process. A new interpreter is spawned to avoid problems when mixing
739 # threads and fork(): only async-safe functions are allowed between
740 # fork() and exec().
741 assert_python_ok("-c", """if True:
742 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200743
Victor Stinner415007e2011-06-13 16:19:06 +0200744 # the default handler terminates the process
745 signum = signal.SIGUSR1
746
747 def kill_later():
748 # wait until the main thread is waiting in sigwait()
749 time.sleep(1)
750 os.kill(os.getpid(), signum)
751
752 # the signal must be blocked by all the threads
753 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
754 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200755 killer.start()
756 received = signal.sigwait([signum])
757 if received != signum:
758 print("sigwait() received %s, not %s" % (received, signum),
759 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200760 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200761 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200762 # unblock the signal, which should have been cleared by sigwait()
763 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
764 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200765
Victor Stinnerb3e72192011-05-08 01:46:11 +0200766 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
767 'need signal.pthread_sigmask()')
768 def test_pthread_sigmask_arguments(self):
769 self.assertRaises(TypeError, signal.pthread_sigmask)
770 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
771 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
772 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
773
774 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
775 'need signal.pthread_sigmask()')
776 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200777 code = """if 1:
778 import signal
779 import os; import threading
780
781 def handler(signum, frame):
782 1/0
783
784 def kill(signum):
785 os.kill(os.getpid(), signum)
786
787 def read_sigmask():
788 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
789
Victor Stinnerb3e72192011-05-08 01:46:11 +0200790 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200791
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200792 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200793 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200794
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200795 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200796 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200797 try:
798 kill(signum)
799 except ZeroDivisionError:
800 pass
801 else:
802 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200803
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200804 # Block and then raise SIGUSR1. The signal is blocked: the signal
805 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200806 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200807 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200808
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200809 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200810 blocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200811 if signum not in blocked:
812 raise Exception("%s not in %s" % (signum, blocked))
813 if old_mask ^ blocked != {signum}:
814 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200815
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200816 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200817 try:
818 # unblock the pending signal calls immediatly the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200819 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200820 except ZeroDivisionError:
821 pass
822 else:
823 raise Exception("ZeroDivisionError not raised")
824 try:
825 kill(signum)
826 except ZeroDivisionError:
827 pass
828 else:
829 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200830
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200831 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200832 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200833 if signum in unblocked:
834 raise Exception("%s in %s" % (signum, unblocked))
835 if blocked ^ unblocked != {signum}:
836 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
837 if old_mask != unblocked:
838 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200839 """
840 assert_python_ok('-c', code)
841
842 @unittest.skipIf(sys.platform == 'freebsd6',
843 "issue #12392: send a signal to the main thread doesn't work "
844 "before the creation of the first thread on FreeBSD 6")
845 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
846 'need signal.pthread_kill()')
847 def test_pthread_kill_main_thread(self):
848 # Test that a signal can be sent to the main thread with pthread_kill()
849 # before any other thread has been created (see issue #12392).
850 code = """if True:
851 import threading
852 import signal
853 import sys
854
855 def handler(signum, frame):
856 sys.exit(3)
857
858 signal.signal(signal.SIGUSR1, handler)
859 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
860 sys.exit(2)
861 """
862
863 with spawn_python('-c', code) as process:
864 stdout, stderr = process.communicate()
865 exitcode = process.wait()
866 if exitcode != 3:
867 raise Exception("Child error (exit code %s): %s" %
868 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200869
870
Thomas Woutersed03b412007-08-28 21:37:11 +0000871def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100872 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200873 support.run_unittest(PosixTests, InterProcessSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500874 WakeupFDTests, WakeupSignalTests,
875 SiginterruptTest, ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200876 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100877 finally:
878 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000879
880
881if __name__ == "__main__":
882 test_main()