blob: c973be8b6ece388a14ee2d825dc7c1ff39b53a05 [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)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000036 except EnvironmentError as e:
37 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.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000107 self.fail('HandlerBCalled exception not thrown')
108 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
143 # throws. The real work happens in self.run_test().
144 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
Brian Curtineccd4d92010-10-01 15:09:53 +0000209 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
210 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
211 signal.SIGTERM):
212 # Set and then reset a handler for signals that work on windows
213 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin3f004b12010-08-06 19:34:52 +0000214
215 with self.assertRaises(ValueError):
216 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000217
218 with self.assertRaises(ValueError):
219 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000220
221
222@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000223class WakeupSignalTests(unittest.TestCase):
Charles-François Natali027f9a32011-10-02 18:36:05 +0200224 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200225 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200226 code = """if 1:
227 import fcntl
228 import os
229 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200230 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000231
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200232 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200233
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200234 def handler(signum, frame):
235 pass
236
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200237 def check_signum(signals):
238 data = os.read(read, len(signals)+1)
239 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200240 if not {!r}:
241 raised = set(raised)
242 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200243 if raised != signals:
244 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200245
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200246 {}
247
248 signal.signal(signal.SIGALRM, handler)
249 read, write = os.pipe()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200250 for fd in (read, write):
251 flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
252 flags = flags | os.O_NONBLOCK
253 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200254 signal.set_wakeup_fd(write)
255
256 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200257 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200258
259 os.close(read)
260 os.close(write)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200261 """.format(signals, ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200262
263 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200264
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000265 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200266 self.check_wakeup("""def test():
267 import select
268 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000269
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200270 TIMEOUT_FULL = 10
271 TIMEOUT_HALF = 5
272
273 signal.alarm(1)
274 before_time = time.time()
275 # We attempt to get a signal during the sleep,
276 # before select is called
277 time.sleep(TIMEOUT_FULL)
278 mid_time = time.time()
279 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200280 if dt >= TIMEOUT_HALF:
281 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200282 select.select([read], [], [], TIMEOUT_FULL)
283 after_time = time.time()
284 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200285 if dt >= TIMEOUT_HALF:
286 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200287 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000288
289 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200290 self.check_wakeup("""def test():
291 import select
292 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000293
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200294 TIMEOUT_FULL = 10
295 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000296
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200297 signal.alarm(1)
298 before_time = time.time()
299 # We attempt to get a signal during the select call
300 try:
301 select.select([read], [], [], TIMEOUT_FULL)
302 except select.error:
303 pass
304 else:
305 raise Exception("select.error not raised")
306 after_time = time.time()
307 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200308 if dt >= TIMEOUT_HALF:
309 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200310 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200311
312 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200313 self.check_wakeup("""def test():
314 signal.signal(signal.SIGUSR1, handler)
315 os.kill(os.getpid(), signal.SIGUSR1)
316 os.kill(os.getpid(), signal.SIGALRM)
317 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000318
Victor Stinnerc13ef662011-05-25 02:35:58 +0200319 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
320 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200321 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200322 self.check_wakeup("""def test():
323 signum1 = signal.SIGUSR1
324 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200325
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200326 signal.signal(signum1, handler)
327 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200328
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200329 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
330 os.kill(os.getpid(), signum1)
331 os.kill(os.getpid(), signum2)
332 # Unblocking the 2 signals calls the C signal handler twice
333 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200334 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200335
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000336
Brian Curtin3f004b12010-08-06 19:34:52 +0000337@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000338class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000339
Victor Stinnerd6284962011-06-20 23:28:09 +0200340 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000341 """Perform a read during which a signal will arrive. Return True if the
342 read is interrupted by the signal and raises an exception. Return False
343 if it returns normally.
344 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200345 # use a subprocess to have only one thread, to have a timeout on the
346 # blocking read and to not touch signal handling in this process
347 code = """if 1:
348 import errno
349 import os
350 import signal
351 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000352
Victor Stinnerd6284962011-06-20 23:28:09 +0200353 interrupt = %r
354 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000355
Victor Stinnerd6284962011-06-20 23:28:09 +0200356 def handler(signum, frame):
357 pass
358
359 signal.signal(signal.SIGALRM, handler)
360 if interrupt is not None:
361 signal.siginterrupt(signal.SIGALRM, interrupt)
362
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200363 print("ready")
364 sys.stdout.flush()
365
Victor Stinnerd6284962011-06-20 23:28:09 +0200366 # run the test twice
367 for loop in range(2):
368 # send a SIGALRM in a second (during the read)
369 signal.alarm(1)
370 try:
371 # blocking call: read from a pipe without data
372 os.read(r, 1)
373 except OSError as err:
374 if err.errno != errno.EINTR:
375 raise
376 else:
377 sys.exit(2)
378 sys.exit(3)
379 """ % (interrupt,)
380 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000381 try:
Victor Stinner45273652011-06-22 22:15:51 +0200382 # wait until the child process is loaded and has started
383 first_line = process.stdout.readline()
384
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200385 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200386 except subprocess.TimeoutExpired:
387 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000388 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200389 else:
Victor Stinner45273652011-06-22 22:15:51 +0200390 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200391 exitcode = process.wait()
392 if exitcode not in (2, 3):
393 raise Exception("Child error (exit code %s): %s"
394 % (exitcode, stdout))
395 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000396
397 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200398 # If a signal handler is installed and siginterrupt is not called
399 # at all, when that signal arrives, it interrupts a syscall that's in
400 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200401 interrupted = self.readpipe_interrupted(None)
402 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000403
404 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200405 # If a signal handler is installed and siginterrupt is called with
406 # a true value for the second argument, when that signal arrives, it
407 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200408 interrupted = self.readpipe_interrupted(True)
409 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000410
411 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200412 # If a signal handler is installed and siginterrupt is called with
413 # a false value for the second argument, when that signal arrives, it
414 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200415 interrupted = self.readpipe_interrupted(False)
416 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000417
418
Brian Curtin3f004b12010-08-06 19:34:52 +0000419@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000420class ItimerTest(unittest.TestCase):
421 def setUp(self):
422 self.hndl_called = False
423 self.hndl_count = 0
424 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000425 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000426
427 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000428 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000429 if self.itimer is not None: # test_itimer_exc doesn't change this attr
430 # just ensure that itimer is stopped
431 signal.setitimer(self.itimer, 0)
432
433 def sig_alrm(self, *args):
434 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000435
436 def sig_vtalrm(self, *args):
437 self.hndl_called = True
438
439 if self.hndl_count > 3:
440 # it shouldn't be here, because it should have been disabled.
441 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
442 "timer.")
443 elif self.hndl_count == 3:
444 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
445 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000446
447 self.hndl_count += 1
448
Martin v. Löwis823725e2008-03-24 13:39:54 +0000449 def sig_prof(self, *args):
450 self.hndl_called = True
451 signal.setitimer(signal.ITIMER_PROF, 0)
452
Martin v. Löwis823725e2008-03-24 13:39:54 +0000453 def test_itimer_exc(self):
454 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
455 # defines it ?
456 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000457 # Negative times are treated as zero on some platforms.
458 if 0:
459 self.assertRaises(signal.ItimerError,
460 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000461
462 def test_itimer_real(self):
463 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000464 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000465 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000466 self.assertEqual(self.hndl_called, True)
467
R. David Murray44546f82010-04-21 01:59:28 +0000468 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000469 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
470 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000471 def test_itimer_virtual(self):
472 self.itimer = signal.ITIMER_VIRTUAL
473 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
474 signal.setitimer(self.itimer, 0.3, 0.2)
475
Mark Dickinson78373472009-10-31 10:39:21 +0000476 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000477 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000478 # use up some virtual time by doing real work
479 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000480 if signal.getitimer(self.itimer) == (0.0, 0.0):
481 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000482 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000483 self.skipTest("timeout: likely cause: machine too slow or load too "
484 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000485
486 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000487 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000488 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000489 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000490
R. David Murray44546f82010-04-21 01:59:28 +0000491 # Issue 3864, unknown if this affects earlier versions of freebsd also
492 @unittest.skipIf(sys.platform=='freebsd6',
493 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000494 def test_itimer_prof(self):
495 self.itimer = signal.ITIMER_PROF
496 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000497 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000498
Mark Dickinson78373472009-10-31 10:39:21 +0000499 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000500 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000501 # do some work
502 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000503 if signal.getitimer(self.itimer) == (0.0, 0.0):
504 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000505 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000506 self.skipTest("timeout: likely cause: machine too slow or load too "
507 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000508
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000509 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000510 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000511 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000512 self.assertEqual(self.hndl_called, True)
513
Victor Stinnera9293352011-04-30 15:21:58 +0200514
Victor Stinner35b300c2011-05-04 13:20:35 +0200515class PendingSignalsTests(unittest.TestCase):
516 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200517 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
518 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200519 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200520 @unittest.skipUnless(hasattr(signal, 'sigpending'),
521 'need signal.sigpending()')
522 def test_sigpending_empty(self):
523 self.assertEqual(signal.sigpending(), set())
524
525 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
526 'need signal.pthread_sigmask()')
527 @unittest.skipUnless(hasattr(signal, 'sigpending'),
528 'need signal.sigpending()')
529 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200530 code = """if 1:
531 import os
532 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200533
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200534 def handler(signum, frame):
535 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200536
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200537 signum = signal.SIGUSR1
538 signal.signal(signum, handler)
539
540 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
541 os.kill(os.getpid(), signum)
542 pending = signal.sigpending()
Victor Stinner0a01f132011-07-04 18:06:35 +0200543 if pending != {signum}:
544 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200545 try:
546 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
547 except ZeroDivisionError:
548 pass
549 else:
550 raise Exception("ZeroDivisionError not raised")
551 """
552 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200553
554 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
555 'need signal.pthread_kill()')
556 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200557 code = """if 1:
558 import signal
559 import threading
560 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200561
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200562 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200563
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200564 def handler(signum, frame):
565 1/0
566
567 signal.signal(signum, handler)
568
569 if sys.platform == 'freebsd6':
570 # Issue #12392 and #12469: send a signal to the main thread
571 # doesn't work before the creation of the first thread on
572 # FreeBSD 6
573 def noop():
574 pass
575 thread = threading.Thread(target=noop)
576 thread.start()
577 thread.join()
578
579 tid = threading.get_ident()
580 try:
581 signal.pthread_kill(tid, signum)
582 except ZeroDivisionError:
583 pass
584 else:
585 raise Exception("ZeroDivisionError not raised")
586 """
587 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200588
Victor Stinner7f294d12011-06-10 14:02:10 +0200589 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
590 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200591 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200592 """
593 test: body of the "def test(signum):" function.
594 blocked: number of the blocked signal
595 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200596 code = '''if 1:
597 import signal
598 import sys
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200599
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200600 def handler(signum, frame):
601 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200602
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200603 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200604
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200605 blocked = %s
606 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200607
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200608 # child: block and wait the signal
609 try:
610 signal.signal(signum, handler)
611 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200612
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200613 # Do the tests
614 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200615
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200616 # The handler must not be called on unblock
617 try:
618 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
619 except ZeroDivisionError:
620 print("the signal handler has been called",
621 file=sys.stderr)
622 sys.exit(1)
623 except BaseException as err:
624 print("error: {}".format(err), file=sys.stderr)
625 sys.stderr.flush()
626 sys.exit(1)
627 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200628
Ross Lagerwallbc808222011-06-25 12:13:40 +0200629 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200630 # process might have several threads running, use a subprocess to have
631 # a single thread.
632 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200633
Victor Stinnerb3e72192011-05-08 01:46:11 +0200634 @unittest.skipUnless(hasattr(signal, 'sigwait'),
635 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200636 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200637 self.wait_helper(signal.SIGALRM, '''
638 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200639 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200640 received = signal.sigwait([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200641 if received != signum:
642 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200643 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200644
645 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
646 'need signal.sigwaitinfo()')
647 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200648 self.wait_helper(signal.SIGALRM, '''
649 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200650 signal.alarm(1)
651 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200652 if info.si_signo != signum:
653 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200654 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200655
656 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
657 'need signal.sigtimedwait()')
658 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200659 self.wait_helper(signal.SIGALRM, '''
660 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200661 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100662 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200663 if info.si_signo != signum:
664 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200665 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200666
Ross Lagerwallbc808222011-06-25 12:13:40 +0200667 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
668 'need signal.sigtimedwait()')
669 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200670 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200671 self.wait_helper(signal.SIGALRM, '''
672 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200673 import os
674 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100675 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200676 if info.si_signo != signum:
677 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200678 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200679
680 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
681 'need signal.sigtimedwait()')
682 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200683 self.wait_helper(signal.SIGALRM, '''
684 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100685 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200686 if received is not None:
687 raise Exception("received=%r" % (received,))
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_negative_timeout(self):
693 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100694 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200695
Ross Lagerwallbc808222011-06-25 12:13:40 +0200696 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
697 'need signal.sigwaitinfo()')
698 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200699 self.wait_helper(signal.SIGUSR1, '''
700 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200701 import errno
702
703 hndl_called = True
704 def alarm_handler(signum, frame):
705 hndl_called = False
706
707 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200708 signal.alarm(1)
709 try:
710 signal.sigwaitinfo([signal.SIGUSR1])
711 except OSError as e:
712 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200713 if not hndl_called:
714 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200715 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200716 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200717 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200718 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200719 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200720
721 @unittest.skipUnless(hasattr(signal, 'sigwait'),
722 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200723 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
724 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200725 @unittest.skipIf(threading is None, "test needs threading module")
726 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200727 # Check that calling sigwait() from a thread doesn't suspend the whole
728 # process. A new interpreter is spawned to avoid problems when mixing
729 # threads and fork(): only async-safe functions are allowed between
730 # fork() and exec().
731 assert_python_ok("-c", """if True:
732 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200733
Victor Stinner415007e2011-06-13 16:19:06 +0200734 # the default handler terminates the process
735 signum = signal.SIGUSR1
736
737 def kill_later():
738 # wait until the main thread is waiting in sigwait()
739 time.sleep(1)
740 os.kill(os.getpid(), signum)
741
742 # the signal must be blocked by all the threads
743 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
744 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200745 killer.start()
746 received = signal.sigwait([signum])
747 if received != signum:
748 print("sigwait() received %s, not %s" % (received, signum),
749 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200750 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200751 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200752 # unblock the signal, which should have been cleared by sigwait()
753 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
754 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200755
Victor Stinnerb3e72192011-05-08 01:46:11 +0200756 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
757 'need signal.pthread_sigmask()')
758 def test_pthread_sigmask_arguments(self):
759 self.assertRaises(TypeError, signal.pthread_sigmask)
760 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
761 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
762 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
763
764 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
765 'need signal.pthread_sigmask()')
766 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200767 code = """if 1:
768 import signal
769 import os; import threading
770
771 def handler(signum, frame):
772 1/0
773
774 def kill(signum):
775 os.kill(os.getpid(), signum)
776
777 def read_sigmask():
778 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
779
Victor Stinnerb3e72192011-05-08 01:46:11 +0200780 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200781
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200782 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200783 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200784
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200785 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200786 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200787 try:
788 kill(signum)
789 except ZeroDivisionError:
790 pass
791 else:
792 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200793
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200794 # Block and then raise SIGUSR1. The signal is blocked: the signal
795 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200796 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200797 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200798
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200799 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200800 blocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200801 if signum not in blocked:
802 raise Exception("%s not in %s" % (signum, blocked))
803 if old_mask ^ blocked != {signum}:
804 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200805
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200806 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200807 try:
808 # unblock the pending signal calls immediatly the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200809 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200810 except ZeroDivisionError:
811 pass
812 else:
813 raise Exception("ZeroDivisionError not raised")
814 try:
815 kill(signum)
816 except ZeroDivisionError:
817 pass
818 else:
819 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200820
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200821 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200822 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200823 if signum in unblocked:
824 raise Exception("%s in %s" % (signum, unblocked))
825 if blocked ^ unblocked != {signum}:
826 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
827 if old_mask != unblocked:
828 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200829 """
830 assert_python_ok('-c', code)
831
832 @unittest.skipIf(sys.platform == 'freebsd6',
833 "issue #12392: send a signal to the main thread doesn't work "
834 "before the creation of the first thread on FreeBSD 6")
835 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
836 'need signal.pthread_kill()')
837 def test_pthread_kill_main_thread(self):
838 # Test that a signal can be sent to the main thread with pthread_kill()
839 # before any other thread has been created (see issue #12392).
840 code = """if True:
841 import threading
842 import signal
843 import sys
844
845 def handler(signum, frame):
846 sys.exit(3)
847
848 signal.signal(signal.SIGUSR1, handler)
849 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
850 sys.exit(2)
851 """
852
853 with spawn_python('-c', code) as process:
854 stdout, stderr = process.communicate()
855 exitcode = process.wait()
856 if exitcode != 3:
857 raise Exception("Child error (exit code %s): %s" %
858 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200859
860
Thomas Woutersed03b412007-08-28 21:37:11 +0000861def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100862 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200863 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100864 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200865 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200866 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100867 finally:
868 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000869
870
871if __name__ == "__main__":
872 test_main()