blob: 1ed4b9e731b176216056406ee027150b7eba625d [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 Stinnerb3e72192011-05-08 01:46:11 +020012try:
13 import threading
14except ImportError:
15 threading = None
Christian Heimesc06950e2008-02-28 21:17:00 +000016
Brian Curtin912443c2010-09-06 16:10:04 +000017if sys.platform in ('os2', 'riscos'):
18 raise unittest.SkipTest("Can't test signal on %s" % sys.platform)
Christian Heimesc06950e2008-02-28 21:17:00 +000019
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000020
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000021class HandlerBCalled(Exception):
22 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000023
Christian Heimes4fbc72b2008-03-22 00:47:35 +000024
25def exit_subprocess():
26 """Use os._exit(0) to exit the current subprocess.
27
28 Otherwise, the test catches the SystemExit and continues executing
29 in parallel with the original test, so you wind up with an
30 exponential number of tests running concurrently.
31 """
32 os._exit(0)
33
34
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000035def ignoring_eintr(__func, *args, **kwargs):
36 try:
37 return __func(*args, **kwargs)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000038 except EnvironmentError as e:
39 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000040 raise
41 return None
42
43
Brian Curtin3f004b12010-08-06 19:34:52 +000044@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000045class InterProcessSignalTests(unittest.TestCase):
46 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000047
Christian Heimescc47b052008-03-25 14:56:36 +000048 def setUp(self):
49 self.using_gc = gc.isenabled()
50 gc.disable()
51
52 def tearDown(self):
53 if self.using_gc:
54 gc.enable()
55
Christian Heimes5e696852008-04-09 08:37:03 +000056 def format_frame(self, frame, limit=None):
57 return ''.join(traceback.format_stack(frame, limit=limit))
58
59 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000060 self.a_called = True
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000061
Christian Heimes5e696852008-04-09 08:37:03 +000062 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000063 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000064 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000065
Christian Heimes4fbc72b2008-03-22 00:47:35 +000066 def wait(self, child):
67 """Wait for child to finish, ignoring EINTR."""
68 while True:
69 try:
70 child.wait()
71 return
72 except OSError as e:
73 if e.errno != errno.EINTR:
74 raise
Fred Drake004d5e62000-10-23 17:22:08 +000075
Christian Heimes4fbc72b2008-03-22 00:47:35 +000076 def run_test(self):
77 # Install handlers. This function runs in a sub-process, so we
78 # don't worry about re-setting the default handlers.
79 signal.signal(signal.SIGHUP, self.handlerA)
80 signal.signal(signal.SIGUSR1, self.handlerB)
81 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
82 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000083
Christian Heimes4fbc72b2008-03-22 00:47:35 +000084 # Variables the signals will modify:
85 self.a_called = False
86 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000087
Christian Heimes4fbc72b2008-03-22 00:47:35 +000088 # Let the sub-processes know who to send signals to.
89 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000090
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000091 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
92 if child:
93 self.wait(child)
94 if not self.a_called:
95 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +000096 self.assertTrue(self.a_called)
97 self.assertFalse(self.b_called)
98 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000099
Christian Heimes5e696852008-04-09 08:37:03 +0000100 # Make sure the signal isn't delivered while the previous
101 # Popen object is being destroyed, because __del__ swallows
102 # exceptions.
103 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000104 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000105 child = subprocess.Popen(['kill', '-USR1', str(pid)])
106 # This wait should be interrupted by the signal's exception.
107 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000108 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000109 self.fail('HandlerBCalled exception not thrown')
110 except HandlerBCalled:
111 self.assertTrue(self.b_called)
112 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000113
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000114 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
115 if child:
116 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000117
118 try:
119 signal.alarm(1)
120 # The race condition in pause doesn't matter in this case,
121 # since alarm is going to raise a KeyboardException, which
122 # will skip the call.
123 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000124 # But if another signal arrives before the alarm, pause
125 # may return early.
126 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000127 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200128 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000129 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000130 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000131 traceback.format_exc())
132 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000133 self.fail("pause returned of its own accord, and the signal"
134 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000135
R. David Murray44546f82010-04-21 01:59:28 +0000136 # Issue 3864, unknown if this affects earlier versions of freebsd also
137 @unittest.skipIf(sys.platform=='freebsd6',
138 'inter process signals not reliable (do not mix well with threading) '
139 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000140 def test_main(self):
141 # This function spawns a child process to insulate the main
142 # test-running process from all the signals. It then
143 # communicates with that child process over a pipe and
144 # re-raises information about any exceptions the child
145 # throws. The real work happens in self.run_test().
146 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000147 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
148 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000149 child = os.fork()
150 if child == 0:
151 # In the child process; run the test and report results
152 # through the pipe.
153 try:
154 done_r.close()
155 # Have to close done_w again here because
156 # exit_subprocess() will skip the enclosing with block.
157 with closing(done_w):
158 try:
159 self.run_test()
160 except:
161 pickle.dump(traceback.format_exc(), done_w)
162 else:
163 pickle.dump(None, done_w)
164 except:
165 print('Uh oh, raised from pickle.')
166 traceback.print_exc()
167 finally:
168 exit_subprocess()
169
170 done_w.close()
171 # Block for up to MAX_DURATION seconds for the test to finish.
172 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
173 if done_r in r:
174 tb = pickle.load(done_r)
175 if tb:
176 self.fail(tb)
177 else:
178 os.kill(child, signal.SIGKILL)
179 self.fail('Test deadlocked after %d seconds.' %
180 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000181
182
Brian Curtin3f004b12010-08-06 19:34:52 +0000183@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200184class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000185 def trivial_signal_handler(self, *args):
186 pass
187
Thomas Woutersed03b412007-08-28 21:37:11 +0000188 def test_out_of_range_signal_number_raises_error(self):
189 self.assertRaises(ValueError, signal.getsignal, 4242)
190
Thomas Woutersed03b412007-08-28 21:37:11 +0000191 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000192 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000193
194 def test_setting_signal_handler_to_none_raises_error(self):
195 self.assertRaises(TypeError, signal.signal,
196 signal.SIGUSR1, None)
197
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000198 def test_getsignal(self):
199 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000200 self.assertEqual(signal.getsignal(signal.SIGHUP),
201 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000202 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000203 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000204
205
Brian Curtin3f004b12010-08-06 19:34:52 +0000206@unittest.skipUnless(sys.platform == "win32", "Windows specific")
207class WindowsSignalTests(unittest.TestCase):
208 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000209 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000210 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +0000211 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
212 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
213 signal.SIGTERM):
214 # Set and then reset a handler for signals that work on windows
215 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin3f004b12010-08-06 19:34:52 +0000216
217 with self.assertRaises(ValueError):
218 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000219
220 with self.assertRaises(ValueError):
221 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000222
223
224@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000225class WakeupSignalTests(unittest.TestCase):
226 TIMEOUT_FULL = 10
227 TIMEOUT_HALF = 5
228
Victor Stinnerc13ef662011-05-25 02:35:58 +0200229 def handler(self, signum, frame):
230 pass
231
Victor Stinner20822682011-05-31 22:31:09 +0200232 def check_signum(self, *signals):
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200233 data = os.read(self.read, len(signals)+1)
234 raised = struct.unpack('%uB' % len(data), data)
Victor Stinner20822682011-05-31 22:31:09 +0200235 # We don't care of the signal delivery order (it's not portable or
236 # reliable)
237 raised = set(raised)
238 signals = set(signals)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200239 self.assertEqual(raised, signals)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200240
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000241 def test_wakeup_fd_early(self):
242 import select
243
244 signal.alarm(1)
245 before_time = time.time()
246 # We attempt to get a signal during the sleep,
247 # before select is called
248 time.sleep(self.TIMEOUT_FULL)
249 mid_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000250 self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000251 select.select([self.read], [], [], self.TIMEOUT_FULL)
252 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000253 self.assertTrue(after_time - mid_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200254 self.check_signum(signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000255
256 def test_wakeup_fd_during(self):
257 import select
258
259 signal.alarm(1)
260 before_time = time.time()
261 # We attempt to get a signal during the select call
262 self.assertRaises(select.error, select.select,
263 [self.read], [], [], self.TIMEOUT_FULL)
264 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000265 self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200266 self.check_signum(signal.SIGALRM)
267
268 def test_signum(self):
Victor Stinnerc13ef662011-05-25 02:35:58 +0200269 old_handler = signal.signal(signal.SIGUSR1, self.handler)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200270 self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)
271 os.kill(os.getpid(), signal.SIGUSR1)
272 os.kill(os.getpid(), signal.SIGALRM)
273 self.check_signum(signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000274
Victor Stinnerc13ef662011-05-25 02:35:58 +0200275 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
276 'need signal.pthread_sigmask()')
277 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
278 'need signal.pthread_kill()')
279 def test_pending(self):
280 signum1 = signal.SIGUSR1
281 signum2 = signal.SIGUSR2
282 tid = threading.current_thread().ident
283
284 old_handler = signal.signal(signum1, self.handler)
285 self.addCleanup(signal.signal, signum1, old_handler)
286 old_handler = signal.signal(signum2, self.handler)
287 self.addCleanup(signal.signal, signum2, old_handler)
288
289 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
290 signal.pthread_kill(tid, signum1)
291 signal.pthread_kill(tid, signum2)
292 # Unblocking the 2 signals calls the C signal handler twice
293 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
294
Victor Stinner20822682011-05-31 22:31:09 +0200295 self.check_signum(signum1, signum2)
Victor Stinnerc13ef662011-05-25 02:35:58 +0200296
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000297 def setUp(self):
298 import fcntl
299
Victor Stinnerc13ef662011-05-25 02:35:58 +0200300 self.alrm = signal.signal(signal.SIGALRM, self.handler)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000301 self.read, self.write = os.pipe()
302 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
303 flags = flags | os.O_NONBLOCK
304 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
305 self.old_wakeup = signal.set_wakeup_fd(self.write)
306
307 def tearDown(self):
308 signal.set_wakeup_fd(self.old_wakeup)
309 os.close(self.read)
310 os.close(self.write)
311 signal.signal(signal.SIGALRM, self.alrm)
312
Brian Curtin3f004b12010-08-06 19:34:52 +0000313@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000314class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000315
316 def setUp(self):
317 """Install a no-op signal handler that can be set to allow
318 interrupts or not, and arrange for the original signal handler to be
319 re-installed when the test is finished.
320 """
Brian Curtin3f004b12010-08-06 19:34:52 +0000321 self.signum = signal.SIGUSR1
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000322 oldhandler = signal.signal(self.signum, lambda x,y: None)
323 self.addCleanup(signal.signal, self.signum, oldhandler)
324
325 def readpipe_interrupted(self):
326 """Perform a read during which a signal will arrive. Return True if the
327 read is interrupted by the signal and raises an exception. Return False
328 if it returns normally.
329 """
330 # Create a pipe that can be used for the read. Also clean it up
331 # when the test is over, since nothing else will (but see below for
332 # the write end).
Christian Heimes8640e742008-02-23 16:23:06 +0000333 r, w = os.pipe()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000334 self.addCleanup(os.close, r)
335
336 # Create another process which can send a signal to this one to try
337 # to interrupt the read.
Christian Heimes8640e742008-02-23 16:23:06 +0000338 ppid = os.getpid()
339 pid = os.fork()
340
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000341 if pid == 0:
342 # Child code: sleep to give the parent enough time to enter the
343 # read() call (there's a race here, but it's really tricky to
344 # eliminate it); then signal the parent process. Also, sleep
345 # again to make it likely that the signal is delivered to the
346 # parent process before the child exits. If the child exits
347 # first, the write end of the pipe will be closed and the test
348 # is invalid.
Christian Heimes8640e742008-02-23 16:23:06 +0000349 try:
350 time.sleep(0.2)
351 os.kill(ppid, self.signum)
352 time.sleep(0.2)
353 finally:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000354 # No matter what, just exit as fast as possible now.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000355 exit_subprocess()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000356 else:
357 # Parent code.
358 # Make sure the child is eventually reaped, else it'll be a
359 # zombie for the rest of the test suite run.
360 self.addCleanup(os.waitpid, pid, 0)
Christian Heimes8640e742008-02-23 16:23:06 +0000361
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000362 # Close the write end of the pipe. The child has a copy, so
363 # it's not really closed until the child exits. We need it to
364 # close when the child exits so that in the non-interrupt case
365 # the read eventually completes, otherwise we could just close
366 # it *after* the test.
Christian Heimes8640e742008-02-23 16:23:06 +0000367 os.close(w)
368
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000369 # Try the read and report whether it is interrupted or not to
370 # the caller.
Christian Heimes8640e742008-02-23 16:23:06 +0000371 try:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000372 d = os.read(r, 1)
Christian Heimes8640e742008-02-23 16:23:06 +0000373 return False
374 except OSError as err:
375 if err.errno != errno.EINTR:
376 raise
377 return True
Christian Heimes8640e742008-02-23 16:23:06 +0000378
379 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200380 # If a signal handler is installed and siginterrupt is not called
381 # at all, when that signal arrives, it interrupts a syscall that's in
382 # progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000383 i = self.readpipe_interrupted()
384 self.assertTrue(i)
385 # Arrival of the signal shouldn't have changed anything.
386 i = self.readpipe_interrupted()
387 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000388
389 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200390 # If a signal handler is installed and siginterrupt is called with
391 # a true value for the second argument, when that signal arrives, it
392 # interrupts a syscall that's in progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000393 signal.siginterrupt(self.signum, 1)
394 i = self.readpipe_interrupted()
395 self.assertTrue(i)
396 # Arrival of the signal shouldn't have changed anything.
397 i = self.readpipe_interrupted()
398 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000399
400 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200401 # If a signal handler is installed and siginterrupt is called with
402 # a false value for the second argument, when that signal arrives, it
403 # does not interrupt a syscall that's in progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000404 signal.siginterrupt(self.signum, 0)
405 i = self.readpipe_interrupted()
406 self.assertFalse(i)
407 # Arrival of the signal shouldn't have changed anything.
408 i = self.readpipe_interrupted()
409 self.assertFalse(i)
410
411
Brian Curtin3f004b12010-08-06 19:34:52 +0000412@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000413class ItimerTest(unittest.TestCase):
414 def setUp(self):
415 self.hndl_called = False
416 self.hndl_count = 0
417 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000418 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000419
420 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000421 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000422 if self.itimer is not None: # test_itimer_exc doesn't change this attr
423 # just ensure that itimer is stopped
424 signal.setitimer(self.itimer, 0)
425
426 def sig_alrm(self, *args):
427 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000428
429 def sig_vtalrm(self, *args):
430 self.hndl_called = True
431
432 if self.hndl_count > 3:
433 # it shouldn't be here, because it should have been disabled.
434 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
435 "timer.")
436 elif self.hndl_count == 3:
437 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
438 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000439
440 self.hndl_count += 1
441
Martin v. Löwis823725e2008-03-24 13:39:54 +0000442 def sig_prof(self, *args):
443 self.hndl_called = True
444 signal.setitimer(signal.ITIMER_PROF, 0)
445
Martin v. Löwis823725e2008-03-24 13:39:54 +0000446 def test_itimer_exc(self):
447 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
448 # defines it ?
449 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000450 # Negative times are treated as zero on some platforms.
451 if 0:
452 self.assertRaises(signal.ItimerError,
453 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000454
455 def test_itimer_real(self):
456 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000457 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000458 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000459 self.assertEqual(self.hndl_called, True)
460
R. David Murray44546f82010-04-21 01:59:28 +0000461 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000462 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
463 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000464 def test_itimer_virtual(self):
465 self.itimer = signal.ITIMER_VIRTUAL
466 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
467 signal.setitimer(self.itimer, 0.3, 0.2)
468
Mark Dickinson78373472009-10-31 10:39:21 +0000469 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000470 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000471 # use up some virtual time by doing real work
472 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000473 if signal.getitimer(self.itimer) == (0.0, 0.0):
474 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000475 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000476 self.skipTest("timeout: likely cause: machine too slow or load too "
477 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000478
479 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000480 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000481 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000482 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000483
R. David Murray44546f82010-04-21 01:59:28 +0000484 # Issue 3864, unknown if this affects earlier versions of freebsd also
485 @unittest.skipIf(sys.platform=='freebsd6',
486 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000487 def test_itimer_prof(self):
488 self.itimer = signal.ITIMER_PROF
489 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000490 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000491
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 Dickinson78373472009-10-31 10:39:21 +0000494 # do some 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_prof 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
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000502 # profiling 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))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000504 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000505 self.assertEqual(self.hndl_called, True)
506
Victor Stinnera9293352011-04-30 15:21:58 +0200507
Victor Stinner35b300c2011-05-04 13:20:35 +0200508class PendingSignalsTests(unittest.TestCase):
509 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200510 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
511 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200512 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200513 def setUp(self):
514 self.has_pthread_kill = hasattr(signal, 'pthread_kill')
515
Victor Stinner35b300c2011-05-04 13:20:35 +0200516 def handler(self, signum, frame):
517 1/0
518
519 def read_sigmask(self):
520 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
521
Victor Stinnerb3e72192011-05-08 01:46:11 +0200522 def can_test_blocked_signals(self, skip):
523 """
524 Check if a blocked signal can be raised to the main thread without
525 calling its signal handler. We need pthread_kill() or exactly one
526 thread (the main thread).
Victor Stinnera9293352011-04-30 15:21:58 +0200527
Victor Stinnerb3e72192011-05-08 01:46:11 +0200528 Return True if it's possible. Otherwise, return False and print a
529 warning if skip is False, or raise a SkipTest exception if skip is
530 True.
531 """
532 if self.has_pthread_kill:
533 return True
Victor Stinnera9293352011-04-30 15:21:58 +0200534
Victor Stinnerf44ce872011-05-03 17:20:31 +0200535 # The fault handler timeout thread masks all signals. If the main
536 # thread masks also SIGUSR1, all threads mask this signal. In this
537 # case, if we send SIGUSR1 to the process, the signal is pending in the
538 # main or the faulthandler timeout thread. Unblock SIGUSR1 in the main
539 # thread calls the signal handler only if the signal is pending for the
Victor Stinnerb3e72192011-05-08 01:46:11 +0200540 # main thread. Stop the faulthandler timeout thread to workaround this
541 # problem.
542 import faulthandler
Victor Stinnerf44ce872011-05-03 17:20:31 +0200543 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner2d4a91e2011-05-03 14:11:22 +0200544
Victor Stinnerb3e72192011-05-08 01:46:11 +0200545 # Issue #11998: The _tkinter module loads the Tcl library which
546 # creates a thread waiting events in select(). This thread receives
547 # signals blocked by all other threads. We cannot test blocked
548 # signals
549 if '_tkinter' in sys.modules:
550 message = ("_tkinter is loaded and pthread_kill() is missing, "
551 "cannot test blocked signals (issue #11998)")
552 if skip:
553 self.skipTest(message)
554 else:
555 print("WARNING: %s" % message)
556 return False
557 return True
558
559 def kill(self, signum):
560 if self.has_pthread_kill:
Victor Stinner2a129742011-05-30 23:02:52 +0200561 tid = threading.get_ident()
Victor Stinnerb3e72192011-05-08 01:46:11 +0200562 signal.pthread_kill(tid, signum)
563 else:
564 pid = os.getpid()
565 os.kill(pid, signum)
566
567 @unittest.skipUnless(hasattr(signal, 'sigpending'),
568 'need signal.sigpending()')
569 def test_sigpending_empty(self):
570 self.assertEqual(signal.sigpending(), set())
571
572 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
573 'need signal.pthread_sigmask()')
574 @unittest.skipUnless(hasattr(signal, 'sigpending'),
575 'need signal.sigpending()')
576 def test_sigpending(self):
577 self.can_test_blocked_signals(True)
578
579 signum = signal.SIGUSR1
580 old_handler = signal.signal(signum, self.handler)
581 self.addCleanup(signal.signal, signum, old_handler)
582
583 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
584 self.kill(signum)
585 self.assertEqual(signal.sigpending(), {signum})
586 with self.assertRaises(ZeroDivisionError):
587 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
588
589 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
590 'need signal.pthread_kill()')
591 def test_pthread_kill(self):
592 signum = signal.SIGUSR1
Victor Stinner2a129742011-05-30 23:02:52 +0200593 current = threading.get_ident()
Victor Stinnerb3e72192011-05-08 01:46:11 +0200594
595 old_handler = signal.signal(signum, self.handler)
596 self.addCleanup(signal.signal, signum, old_handler)
597
598 with self.assertRaises(ZeroDivisionError):
599 signal.pthread_kill(current, signum)
600
601 @unittest.skipUnless(hasattr(signal, 'sigwait'),
602 'need signal.sigwait()')
603 def test_sigwait(self):
604 old_handler = signal.signal(signal.SIGALRM, self.handler)
605 self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
606
607 signal.alarm(1)
608 self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)
609
Victor Stinner10c30d62011-06-10 01:39:53 +0200610 @unittest.skipUnless(hasattr(signal, 'sigwait'),
611 'need signal.sigwait()')
612 @unittest.skipIf(threading is None, "test needs threading module")
613 def test_sigwait_thread(self):
614 signum = signal.SIGUSR1
615 old_handler = signal.signal(signum, self.handler)
616 self.addCleanup(signal.signal, signum, old_handler)
617
618 def kill_later():
619 time.sleep(1)
620 os.kill(os.getpid(), signum)
621
622 killer = threading.Thread(target=kill_later)
623 killer.start()
624 try:
625 self.assertEqual(signal.sigwait([signum]), signum)
626 finally:
627 killer.join()
628
Victor Stinnerb3e72192011-05-08 01:46:11 +0200629 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
630 'need signal.pthread_sigmask()')
631 def test_pthread_sigmask_arguments(self):
632 self.assertRaises(TypeError, signal.pthread_sigmask)
633 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
634 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
635 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
636
637 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
638 'need signal.pthread_sigmask()')
639 def test_pthread_sigmask(self):
640 test_blocked_signals = self.can_test_blocked_signals(False)
641 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200642
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200643 # Install our signal handler
Victor Stinner35b300c2011-05-04 13:20:35 +0200644 old_handler = signal.signal(signum, self.handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200645 self.addCleanup(signal.signal, signum, old_handler)
646
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200647 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200648 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
649 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200650 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200651 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200652
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200653 # Block and then raise SIGUSR1. The signal is blocked: the signal
654 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200655 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerb3e72192011-05-08 01:46:11 +0200656 if test_blocked_signals:
657 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200658
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200659 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200660 blocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200661 self.assertIn(signum, blocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200662 self.assertEqual(old_mask ^ blocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200663
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200664 # Unblock SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200665 if test_blocked_signals:
Victor Stinner6fd49e12011-05-04 12:38:03 +0200666 with self.assertRaises(ZeroDivisionError):
667 # unblock the pending signal calls immediatly the signal handler
668 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
669 else:
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200670 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
671 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200672 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200673
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200674 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200675 unblocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200676 self.assertNotIn(signum, unblocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200677 self.assertEqual(blocked ^ unblocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200678 self.assertSequenceEqual(old_mask, unblocked)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200679 # Finally, restore the previous signal handler and the signal mask
Victor Stinnera9293352011-04-30 15:21:58 +0200680
681
Thomas Woutersed03b412007-08-28 21:37:11 +0000682def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100683 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200684 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100685 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200686 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200687 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100688 finally:
689 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000690
691
692if __name__ == "__main__":
693 test_main()