blob: 9b4ba5016ee400e4f087215b55ff997889a08afc [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
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000212 checked = set()
Brian Curtineccd4d92010-10-01 15:09:53 +0000213 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
214 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
215 signal.SIGTERM):
Nick Coghlan60b3ac72013-08-03 22:56:30 +1000216 # Set and then reset a handler for signals that work on windows.
217 # Issue #18396, only for signals without a C-level handler.
218 if signal.getsignal(sig) is not None:
219 signal.signal(sig, signal.signal(sig, handler))
220 checked.add(sig)
221 # Issue #18396: Ensure the above loop at least tested *something*
222 self.assertTrue(checked)
Brian Curtin3f004b12010-08-06 19:34:52 +0000223
224 with self.assertRaises(ValueError):
225 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000226
227 with self.assertRaises(ValueError):
228 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000229
230
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500231class WakeupFDTests(unittest.TestCase):
232
233 def test_invalid_fd(self):
234 fd = support.make_bad_fd()
235 self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
236
237
Brian Curtin3f004b12010-08-06 19:34:52 +0000238@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000239class WakeupSignalTests(unittest.TestCase):
Charles-François Natali027f9a32011-10-02 18:36:05 +0200240 def check_wakeup(self, test_body, *signals, ordered=True):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200241 # use a subprocess to have only one thread
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200242 code = """if 1:
243 import fcntl
244 import os
245 import signal
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200246 import struct
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000247
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200248 signals = {!r}
Victor Stinnerc13ef662011-05-25 02:35:58 +0200249
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200250 def handler(signum, frame):
251 pass
252
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200253 def check_signum(signals):
254 data = os.read(read, len(signals)+1)
255 raised = struct.unpack('%uB' % len(data), data)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200256 if not {!r}:
257 raised = set(raised)
258 signals = set(signals)
Victor Stinner0a01f132011-07-04 18:06:35 +0200259 if raised != signals:
260 raise Exception("%r != %r" % (raised, signals))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200261
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200262 {}
263
264 signal.signal(signal.SIGALRM, handler)
265 read, write = os.pipe()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200266 for fd in (read, write):
267 flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
268 flags = flags | os.O_NONBLOCK
269 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200270 signal.set_wakeup_fd(write)
271
272 test()
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200273 check_signum(signals)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200274
275 os.close(read)
276 os.close(write)
Charles-François Natali027f9a32011-10-02 18:36:05 +0200277 """.format(signals, ordered, test_body)
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200278
279 assert_python_ok('-c', code)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200280
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000281 def test_wakeup_fd_early(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200282 self.check_wakeup("""def test():
283 import select
284 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000285
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200286 TIMEOUT_FULL = 10
287 TIMEOUT_HALF = 5
288
289 signal.alarm(1)
290 before_time = time.time()
291 # We attempt to get a signal during the sleep,
292 # before select is called
293 time.sleep(TIMEOUT_FULL)
294 mid_time = time.time()
295 dt = mid_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200296 if dt >= TIMEOUT_HALF:
297 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200298 select.select([read], [], [], TIMEOUT_FULL)
299 after_time = time.time()
300 dt = after_time - mid_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200301 if dt >= TIMEOUT_HALF:
302 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200303 """, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000304
305 def test_wakeup_fd_during(self):
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200306 self.check_wakeup("""def test():
307 import select
308 import time
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000309
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200310 TIMEOUT_FULL = 10
311 TIMEOUT_HALF = 5
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000312
Victor Stinnere40b3aa2011-07-04 17:35:10 +0200313 signal.alarm(1)
314 before_time = time.time()
315 # We attempt to get a signal during the select call
316 try:
317 select.select([read], [], [], TIMEOUT_FULL)
318 except select.error:
319 pass
320 else:
321 raise Exception("select.error not raised")
322 after_time = time.time()
323 dt = after_time - before_time
Victor Stinner0a01f132011-07-04 18:06:35 +0200324 if dt >= TIMEOUT_HALF:
325 raise Exception("%s >= %s" % (dt, TIMEOUT_HALF))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200326 """, signal.SIGALRM)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200327
328 def test_signum(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200329 self.check_wakeup("""def test():
330 signal.signal(signal.SIGUSR1, handler)
331 os.kill(os.getpid(), signal.SIGUSR1)
332 os.kill(os.getpid(), signal.SIGALRM)
333 """, signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000334
Victor Stinnerc13ef662011-05-25 02:35:58 +0200335 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
336 'need signal.pthread_sigmask()')
Victor Stinnerc13ef662011-05-25 02:35:58 +0200337 def test_pending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200338 self.check_wakeup("""def test():
339 signum1 = signal.SIGUSR1
340 signum2 = signal.SIGUSR2
Victor Stinnerc13ef662011-05-25 02:35:58 +0200341
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200342 signal.signal(signum1, handler)
343 signal.signal(signum2, handler)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200344
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200345 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
346 os.kill(os.getpid(), signum1)
347 os.kill(os.getpid(), signum2)
348 # Unblocking the 2 signals calls the C signal handler twice
349 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
Charles-François Natali027f9a32011-10-02 18:36:05 +0200350 """, signal.SIGUSR1, signal.SIGUSR2, ordered=False)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200351
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000352
Brian Curtin3f004b12010-08-06 19:34:52 +0000353@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000354class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000355
Victor Stinnerd6284962011-06-20 23:28:09 +0200356 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000357 """Perform a read during which a signal will arrive. Return True if the
358 read is interrupted by the signal and raises an exception. Return False
359 if it returns normally.
360 """
Victor Stinnerd6284962011-06-20 23:28:09 +0200361 # use a subprocess to have only one thread, to have a timeout on the
362 # blocking read and to not touch signal handling in this process
363 code = """if 1:
364 import errno
365 import os
366 import signal
367 import sys
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000368
Victor Stinnerd6284962011-06-20 23:28:09 +0200369 interrupt = %r
370 r, w = os.pipe()
Christian Heimes8640e742008-02-23 16:23:06 +0000371
Victor Stinnerd6284962011-06-20 23:28:09 +0200372 def handler(signum, frame):
373 pass
374
375 signal.signal(signal.SIGALRM, handler)
376 if interrupt is not None:
377 signal.siginterrupt(signal.SIGALRM, interrupt)
378
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200379 print("ready")
380 sys.stdout.flush()
381
Victor Stinnerd6284962011-06-20 23:28:09 +0200382 # run the test twice
383 for loop in range(2):
384 # send a SIGALRM in a second (during the read)
385 signal.alarm(1)
386 try:
387 # blocking call: read from a pipe without data
388 os.read(r, 1)
389 except OSError as err:
390 if err.errno != errno.EINTR:
391 raise
392 else:
393 sys.exit(2)
394 sys.exit(3)
395 """ % (interrupt,)
396 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000397 try:
Victor Stinner45273652011-06-22 22:15:51 +0200398 # wait until the child process is loaded and has started
399 first_line = process.stdout.readline()
400
Victor Stinner19e5bcd2011-07-01 15:59:54 +0200401 stdout, stderr = process.communicate(timeout=5.0)
Victor Stinnerd6284962011-06-20 23:28:09 +0200402 except subprocess.TimeoutExpired:
403 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000404 return False
Victor Stinnerd6284962011-06-20 23:28:09 +0200405 else:
Victor Stinner45273652011-06-22 22:15:51 +0200406 stdout = first_line + stdout
Victor Stinnerd6284962011-06-20 23:28:09 +0200407 exitcode = process.wait()
408 if exitcode not in (2, 3):
409 raise Exception("Child error (exit code %s): %s"
410 % (exitcode, stdout))
411 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000412
413 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200414 # If a signal handler is installed and siginterrupt is not called
415 # at all, when that signal arrives, it interrupts a syscall that's in
416 # progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200417 interrupted = self.readpipe_interrupted(None)
418 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000419
420 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200421 # If a signal handler is installed and siginterrupt is called with
422 # a true value for the second argument, when that signal arrives, it
423 # interrupts a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200424 interrupted = self.readpipe_interrupted(True)
425 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000426
427 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200428 # If a signal handler is installed and siginterrupt is called with
429 # a false value for the second argument, when that signal arrives, it
430 # does not interrupt a syscall that's in progress.
Victor Stinnerd6284962011-06-20 23:28:09 +0200431 interrupted = self.readpipe_interrupted(False)
432 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000433
434
Brian Curtin3f004b12010-08-06 19:34:52 +0000435@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000436class ItimerTest(unittest.TestCase):
437 def setUp(self):
438 self.hndl_called = False
439 self.hndl_count = 0
440 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000441 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000442
443 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000444 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000445 if self.itimer is not None: # test_itimer_exc doesn't change this attr
446 # just ensure that itimer is stopped
447 signal.setitimer(self.itimer, 0)
448
449 def sig_alrm(self, *args):
450 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000451
452 def sig_vtalrm(self, *args):
453 self.hndl_called = True
454
455 if self.hndl_count > 3:
456 # it shouldn't be here, because it should have been disabled.
457 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
458 "timer.")
459 elif self.hndl_count == 3:
460 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
461 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000462
463 self.hndl_count += 1
464
Martin v. Löwis823725e2008-03-24 13:39:54 +0000465 def sig_prof(self, *args):
466 self.hndl_called = True
467 signal.setitimer(signal.ITIMER_PROF, 0)
468
Martin v. Löwis823725e2008-03-24 13:39:54 +0000469 def test_itimer_exc(self):
470 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
471 # defines it ?
472 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000473 # Negative times are treated as zero on some platforms.
474 if 0:
475 self.assertRaises(signal.ItimerError,
476 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000477
478 def test_itimer_real(self):
479 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000480 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000481 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000482 self.assertEqual(self.hndl_called, True)
483
R. David Murray44546f82010-04-21 01:59:28 +0000484 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000485 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
486 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000487 def test_itimer_virtual(self):
488 self.itimer = signal.ITIMER_VIRTUAL
489 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
490 signal.setitimer(self.itimer, 0.3, 0.2)
491
Mark Dickinson78373472009-10-31 10:39:21 +0000492 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000493 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000494 # use up some virtual time by doing real work
495 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000496 if signal.getitimer(self.itimer) == (0.0, 0.0):
497 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000498 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000499 self.skipTest("timeout: likely cause: machine too slow or load too "
500 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000501
502 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000503 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000504 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000505 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000506
R. David Murray44546f82010-04-21 01:59:28 +0000507 # Issue 3864, unknown if this affects earlier versions of freebsd also
508 @unittest.skipIf(sys.platform=='freebsd6',
509 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000510 def test_itimer_prof(self):
511 self.itimer = signal.ITIMER_PROF
512 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000513 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000514
Mark Dickinson78373472009-10-31 10:39:21 +0000515 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000516 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000517 # do some work
518 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000519 if signal.getitimer(self.itimer) == (0.0, 0.0):
520 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000521 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000522 self.skipTest("timeout: likely cause: machine too slow or load too "
523 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000524
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000525 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000526 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000527 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000528 self.assertEqual(self.hndl_called, True)
529
Victor Stinnera9293352011-04-30 15:21:58 +0200530
Victor Stinner35b300c2011-05-04 13:20:35 +0200531class PendingSignalsTests(unittest.TestCase):
532 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200533 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
534 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200535 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200536 @unittest.skipUnless(hasattr(signal, 'sigpending'),
537 'need signal.sigpending()')
538 def test_sigpending_empty(self):
539 self.assertEqual(signal.sigpending(), set())
540
541 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
542 'need signal.pthread_sigmask()')
543 @unittest.skipUnless(hasattr(signal, 'sigpending'),
544 'need signal.sigpending()')
545 def test_sigpending(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200546 code = """if 1:
547 import os
548 import signal
Victor Stinnerb3e72192011-05-08 01:46:11 +0200549
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200550 def handler(signum, frame):
551 1/0
Victor Stinnerb3e72192011-05-08 01:46:11 +0200552
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200553 signum = signal.SIGUSR1
554 signal.signal(signum, handler)
555
556 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
557 os.kill(os.getpid(), signum)
558 pending = signal.sigpending()
Victor Stinner0a01f132011-07-04 18:06:35 +0200559 if pending != {signum}:
560 raise Exception('%s != {%s}' % (pending, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200561 try:
562 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
563 except ZeroDivisionError:
564 pass
565 else:
566 raise Exception("ZeroDivisionError not raised")
567 """
568 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200569
570 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
571 'need signal.pthread_kill()')
572 def test_pthread_kill(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200573 code = """if 1:
574 import signal
575 import threading
576 import sys
Victor Stinnerb3e72192011-05-08 01:46:11 +0200577
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200578 signum = signal.SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200579
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200580 def handler(signum, frame):
581 1/0
582
583 signal.signal(signum, handler)
584
585 if sys.platform == 'freebsd6':
586 # Issue #12392 and #12469: send a signal to the main thread
587 # doesn't work before the creation of the first thread on
588 # FreeBSD 6
589 def noop():
590 pass
591 thread = threading.Thread(target=noop)
592 thread.start()
593 thread.join()
594
595 tid = threading.get_ident()
596 try:
597 signal.pthread_kill(tid, signum)
598 except ZeroDivisionError:
599 pass
600 else:
601 raise Exception("ZeroDivisionError not raised")
602 """
603 assert_python_ok('-c', code)
Victor Stinnerb3e72192011-05-08 01:46:11 +0200604
Victor Stinner7f294d12011-06-10 14:02:10 +0200605 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
606 'need signal.pthread_sigmask()')
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200607 def wait_helper(self, blocked, test):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200608 """
609 test: body of the "def test(signum):" function.
610 blocked: number of the blocked signal
611 """
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200612 code = '''if 1:
613 import signal
614 import sys
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200615
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200616 def handler(signum, frame):
617 1/0
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200618
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200619 %s
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200620
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200621 blocked = %s
622 signum = signal.SIGALRM
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200623
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200624 # child: block and wait the signal
625 try:
626 signal.signal(signum, handler)
627 signal.pthread_sigmask(signal.SIG_BLOCK, [blocked])
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200628
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200629 # Do the tests
630 test(signum)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200631
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200632 # The handler must not be called on unblock
633 try:
634 signal.pthread_sigmask(signal.SIG_UNBLOCK, [blocked])
635 except ZeroDivisionError:
636 print("the signal handler has been called",
637 file=sys.stderr)
638 sys.exit(1)
639 except BaseException as err:
640 print("error: {}".format(err), file=sys.stderr)
641 sys.stderr.flush()
642 sys.exit(1)
643 ''' % (test.strip(), blocked)
Victor Stinner415007e2011-06-13 16:19:06 +0200644
Ross Lagerwallbc808222011-06-25 12:13:40 +0200645 # sig*wait* must be called with the signal blocked: since the current
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200646 # process might have several threads running, use a subprocess to have
647 # a single thread.
648 assert_python_ok('-c', code)
Victor Stinneraf494602011-06-10 12:48:13 +0200649
Victor Stinnerb3e72192011-05-08 01:46:11 +0200650 @unittest.skipUnless(hasattr(signal, 'sigwait'),
651 'need signal.sigwait()')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200652 def test_sigwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200653 self.wait_helper(signal.SIGALRM, '''
654 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200655 signal.alarm(1)
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200656 received = signal.sigwait([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200657 if received != signum:
658 raise Exception('received %s, not %s' % (received, signum))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200659 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200660
661 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
662 'need signal.sigwaitinfo()')
663 def test_sigwaitinfo(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200664 self.wait_helper(signal.SIGALRM, '''
665 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200666 signal.alarm(1)
667 info = signal.sigwaitinfo([signum])
Victor Stinner0a01f132011-07-04 18:06:35 +0200668 if info.si_signo != signum:
669 raise Exception("info.si_signo != %s" % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200670 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200671
672 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
673 'need signal.sigtimedwait()')
674 def test_sigtimedwait(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200675 self.wait_helper(signal.SIGALRM, '''
676 def test(signum):
Ross Lagerwallbc808222011-06-25 12:13:40 +0200677 signal.alarm(1)
Victor Stinner643cd682012-03-02 22:54:03 +0100678 info = signal.sigtimedwait([signum], 10.1000)
Victor Stinner0a01f132011-07-04 18:06:35 +0200679 if info.si_signo != signum:
680 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200681 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200682
Ross Lagerwallbc808222011-06-25 12:13:40 +0200683 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
684 'need signal.sigtimedwait()')
685 def test_sigtimedwait_poll(self):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200686 # check that polling with sigtimedwait works
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200687 self.wait_helper(signal.SIGALRM, '''
688 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200689 import os
690 os.kill(os.getpid(), signum)
Victor Stinner643cd682012-03-02 22:54:03 +0100691 info = signal.sigtimedwait([signum], 0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200692 if info.si_signo != signum:
693 raise Exception('info.si_signo != %s' % signum)
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200694 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200695
696 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
697 'need signal.sigtimedwait()')
698 def test_sigtimedwait_timeout(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200699 self.wait_helper(signal.SIGALRM, '''
700 def test(signum):
Victor Stinner643cd682012-03-02 22:54:03 +0100701 received = signal.sigtimedwait([signum], 1.0)
Victor Stinner0a01f132011-07-04 18:06:35 +0200702 if received is not None:
703 raise Exception("received=%r" % (received,))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200704 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200705
706 @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
707 'need signal.sigtimedwait()')
708 def test_sigtimedwait_negative_timeout(self):
709 signum = signal.SIGALRM
Victor Stinner643cd682012-03-02 22:54:03 +0100710 self.assertRaises(ValueError, signal.sigtimedwait, [signum], -1.0)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200711
Ross Lagerwallbc808222011-06-25 12:13:40 +0200712 @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
713 'need signal.sigwaitinfo()')
Victor Stinner91f9bdd2013-06-17 21:51:56 +0200714 # Issue #18238: sigwaitinfo() can be interrupted on Linux (raises
715 # InterruptedError), but not on AIX
716 @unittest.skipIf(sys.platform.startswith("aix"),
717 'signal.sigwaitinfo() cannot be interrupted on AIX')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200718 def test_sigwaitinfo_interrupted(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200719 self.wait_helper(signal.SIGUSR1, '''
720 def test(signum):
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200721 import errno
722
723 hndl_called = True
724 def alarm_handler(signum, frame):
725 hndl_called = False
726
727 signal.signal(signal.SIGALRM, alarm_handler)
Ross Lagerwallbc808222011-06-25 12:13:40 +0200728 signal.alarm(1)
729 try:
730 signal.sigwaitinfo([signal.SIGUSR1])
731 except OSError as e:
732 if e.errno == errno.EINTR:
Victor Stinner0a01f132011-07-04 18:06:35 +0200733 if not hndl_called:
734 raise Exception("SIGALRM handler not called")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200735 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200736 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Ross Lagerwallbc808222011-06-25 12:13:40 +0200737 else:
Victor Stinner9e8b82f2011-06-29 10:43:02 +0200738 raise Exception("Expected EINTR to be raised by sigwaitinfo")
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200739 ''')
Ross Lagerwallbc808222011-06-25 12:13:40 +0200740
741 @unittest.skipUnless(hasattr(signal, 'sigwait'),
742 'need signal.sigwait()')
Victor Stinner415007e2011-06-13 16:19:06 +0200743 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
744 'need signal.pthread_sigmask()')
Victor Stinner10c30d62011-06-10 01:39:53 +0200745 @unittest.skipIf(threading is None, "test needs threading module")
746 def test_sigwait_thread(self):
Victor Stinner415007e2011-06-13 16:19:06 +0200747 # Check that calling sigwait() from a thread doesn't suspend the whole
748 # process. A new interpreter is spawned to avoid problems when mixing
749 # threads and fork(): only async-safe functions are allowed between
750 # fork() and exec().
751 assert_python_ok("-c", """if True:
752 import os, threading, sys, time, signal
Victor Stinner10c30d62011-06-10 01:39:53 +0200753
Victor Stinner415007e2011-06-13 16:19:06 +0200754 # the default handler terminates the process
755 signum = signal.SIGUSR1
756
757 def kill_later():
758 # wait until the main thread is waiting in sigwait()
759 time.sleep(1)
760 os.kill(os.getpid(), signum)
761
762 # the signal must be blocked by all the threads
763 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
764 killer = threading.Thread(target=kill_later)
Victor Stinneraf494602011-06-10 12:48:13 +0200765 killer.start()
766 received = signal.sigwait([signum])
767 if received != signum:
768 print("sigwait() received %s, not %s" % (received, signum),
769 file=sys.stderr)
Victor Stinner415007e2011-06-13 16:19:06 +0200770 sys.exit(1)
Victor Stinner10c30d62011-06-10 01:39:53 +0200771 killer.join()
Victor Stinner415007e2011-06-13 16:19:06 +0200772 # unblock the signal, which should have been cleared by sigwait()
773 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
774 """)
Victor Stinneraf494602011-06-10 12:48:13 +0200775
Victor Stinnerb3e72192011-05-08 01:46:11 +0200776 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
777 'need signal.pthread_sigmask()')
778 def test_pthread_sigmask_arguments(self):
779 self.assertRaises(TypeError, signal.pthread_sigmask)
780 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
781 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
782 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
783
784 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
785 'need signal.pthread_sigmask()')
786 def test_pthread_sigmask(self):
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200787 code = """if 1:
788 import signal
789 import os; import threading
790
791 def handler(signum, frame):
792 1/0
793
794 def kill(signum):
795 os.kill(os.getpid(), signum)
796
797 def read_sigmask():
798 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
799
Victor Stinnerb3e72192011-05-08 01:46:11 +0200800 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200801
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200802 # Install our signal handler
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200803 old_handler = signal.signal(signum, handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200804
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200805 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200806 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200807 try:
808 kill(signum)
809 except ZeroDivisionError:
810 pass
811 else:
812 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200813
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200814 # Block and then raise SIGUSR1. The signal is blocked: the signal
815 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200816 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200817 kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200818
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200819 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200820 blocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200821 if signum not in blocked:
822 raise Exception("%s not in %s" % (signum, blocked))
823 if old_mask ^ blocked != {signum}:
824 raise Exception("%s ^ %s != {%s}" % (old_mask, blocked, signum))
Victor Stinnera9293352011-04-30 15:21:58 +0200825
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200826 # Unblock SIGUSR1
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200827 try:
828 # unblock the pending signal calls immediatly the signal handler
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200829 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200830 except ZeroDivisionError:
831 pass
832 else:
833 raise Exception("ZeroDivisionError not raised")
834 try:
835 kill(signum)
836 except ZeroDivisionError:
837 pass
838 else:
839 raise Exception("ZeroDivisionError not raised")
Victor Stinnera9293352011-04-30 15:21:58 +0200840
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200841 # Check the new mask
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200842 unblocked = read_sigmask()
Victor Stinner0a01f132011-07-04 18:06:35 +0200843 if signum in unblocked:
844 raise Exception("%s in %s" % (signum, unblocked))
845 if blocked ^ unblocked != {signum}:
846 raise Exception("%s ^ %s != {%s}" % (blocked, unblocked, signum))
847 if old_mask != unblocked:
848 raise Exception("%s != %s" % (old_mask, unblocked))
Victor Stinnerd554cdf2011-07-04 17:49:40 +0200849 """
850 assert_python_ok('-c', code)
851
852 @unittest.skipIf(sys.platform == 'freebsd6',
853 "issue #12392: send a signal to the main thread doesn't work "
854 "before the creation of the first thread on FreeBSD 6")
855 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
856 'need signal.pthread_kill()')
857 def test_pthread_kill_main_thread(self):
858 # Test that a signal can be sent to the main thread with pthread_kill()
859 # before any other thread has been created (see issue #12392).
860 code = """if True:
861 import threading
862 import signal
863 import sys
864
865 def handler(signum, frame):
866 sys.exit(3)
867
868 signal.signal(signal.SIGUSR1, handler)
869 signal.pthread_kill(threading.get_ident(), signal.SIGUSR1)
870 sys.exit(2)
871 """
872
873 with spawn_python('-c', code) as process:
874 stdout, stderr = process.communicate()
875 exitcode = process.wait()
876 if exitcode != 3:
877 raise Exception("Child error (exit code %s): %s" %
878 (exitcode, stdout))
Victor Stinnera9293352011-04-30 15:21:58 +0200879
880
Thomas Woutersed03b412007-08-28 21:37:11 +0000881def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100882 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200883 support.run_unittest(PosixTests, InterProcessSignalTests,
Benjamin Petersonc68a4a02013-01-18 00:10:24 -0500884 WakeupFDTests, WakeupSignalTests,
885 SiginterruptTest, ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200886 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100887 finally:
888 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000889
890
891if __name__ == "__main__":
892 test_main()