blob: cdd3f3e3a4d50a8ee4eefa1d7f9866b25b8ab088 [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
232 def check_signum(self, *signals, **kw):
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 Stinnerc13ef662011-05-25 02:35:58 +0200235 if kw.get('unordered', False):
236 raised = set(raised)
237 signals = set(signals)
238 self.assertEqual(raised, signals)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200239
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000240 def test_wakeup_fd_early(self):
241 import select
242
243 signal.alarm(1)
244 before_time = time.time()
245 # We attempt to get a signal during the sleep,
246 # before select is called
247 time.sleep(self.TIMEOUT_FULL)
248 mid_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000249 self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000250 select.select([self.read], [], [], self.TIMEOUT_FULL)
251 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000252 self.assertTrue(after_time - mid_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200253 self.check_signum(signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000254
255 def test_wakeup_fd_during(self):
256 import select
257
258 signal.alarm(1)
259 before_time = time.time()
260 # We attempt to get a signal during the select call
261 self.assertRaises(select.error, select.select,
262 [self.read], [], [], self.TIMEOUT_FULL)
263 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000264 self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200265 self.check_signum(signal.SIGALRM)
266
267 def test_signum(self):
Victor Stinnerc13ef662011-05-25 02:35:58 +0200268 old_handler = signal.signal(signal.SIGUSR1, self.handler)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200269 self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)
270 os.kill(os.getpid(), signal.SIGUSR1)
271 os.kill(os.getpid(), signal.SIGALRM)
272 self.check_signum(signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000273
Victor Stinnerc13ef662011-05-25 02:35:58 +0200274 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
275 'need signal.pthread_sigmask()')
276 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
277 'need signal.pthread_kill()')
278 def test_pending(self):
279 signum1 = signal.SIGUSR1
280 signum2 = signal.SIGUSR2
281 tid = threading.current_thread().ident
282
283 old_handler = signal.signal(signum1, self.handler)
284 self.addCleanup(signal.signal, signum1, old_handler)
285 old_handler = signal.signal(signum2, self.handler)
286 self.addCleanup(signal.signal, signum2, old_handler)
287
288 signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
289 signal.pthread_kill(tid, signum1)
290 signal.pthread_kill(tid, signum2)
291 # Unblocking the 2 signals calls the C signal handler twice
292 signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
293
294 self.check_signum(signum1, signum2, unordered=True)
295
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000296 def setUp(self):
297 import fcntl
298
Victor Stinnerc13ef662011-05-25 02:35:58 +0200299 self.alrm = signal.signal(signal.SIGALRM, self.handler)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000300 self.read, self.write = os.pipe()
301 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
302 flags = flags | os.O_NONBLOCK
303 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
304 self.old_wakeup = signal.set_wakeup_fd(self.write)
305
306 def tearDown(self):
307 signal.set_wakeup_fd(self.old_wakeup)
308 os.close(self.read)
309 os.close(self.write)
310 signal.signal(signal.SIGALRM, self.alrm)
311
Brian Curtin3f004b12010-08-06 19:34:52 +0000312@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000313class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000314
315 def setUp(self):
316 """Install a no-op signal handler that can be set to allow
317 interrupts or not, and arrange for the original signal handler to be
318 re-installed when the test is finished.
319 """
Brian Curtin3f004b12010-08-06 19:34:52 +0000320 self.signum = signal.SIGUSR1
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000321 oldhandler = signal.signal(self.signum, lambda x,y: None)
322 self.addCleanup(signal.signal, self.signum, oldhandler)
323
324 def readpipe_interrupted(self):
325 """Perform a read during which a signal will arrive. Return True if the
326 read is interrupted by the signal and raises an exception. Return False
327 if it returns normally.
328 """
329 # Create a pipe that can be used for the read. Also clean it up
330 # when the test is over, since nothing else will (but see below for
331 # the write end).
Christian Heimes8640e742008-02-23 16:23:06 +0000332 r, w = os.pipe()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000333 self.addCleanup(os.close, r)
334
335 # Create another process which can send a signal to this one to try
336 # to interrupt the read.
Christian Heimes8640e742008-02-23 16:23:06 +0000337 ppid = os.getpid()
338 pid = os.fork()
339
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000340 if pid == 0:
341 # Child code: sleep to give the parent enough time to enter the
342 # read() call (there's a race here, but it's really tricky to
343 # eliminate it); then signal the parent process. Also, sleep
344 # again to make it likely that the signal is delivered to the
345 # parent process before the child exits. If the child exits
346 # first, the write end of the pipe will be closed and the test
347 # is invalid.
Christian Heimes8640e742008-02-23 16:23:06 +0000348 try:
349 time.sleep(0.2)
350 os.kill(ppid, self.signum)
351 time.sleep(0.2)
352 finally:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000353 # No matter what, just exit as fast as possible now.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000354 exit_subprocess()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000355 else:
356 # Parent code.
357 # Make sure the child is eventually reaped, else it'll be a
358 # zombie for the rest of the test suite run.
359 self.addCleanup(os.waitpid, pid, 0)
Christian Heimes8640e742008-02-23 16:23:06 +0000360
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000361 # Close the write end of the pipe. The child has a copy, so
362 # it's not really closed until the child exits. We need it to
363 # close when the child exits so that in the non-interrupt case
364 # the read eventually completes, otherwise we could just close
365 # it *after* the test.
Christian Heimes8640e742008-02-23 16:23:06 +0000366 os.close(w)
367
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000368 # Try the read and report whether it is interrupted or not to
369 # the caller.
Christian Heimes8640e742008-02-23 16:23:06 +0000370 try:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000371 d = os.read(r, 1)
Christian Heimes8640e742008-02-23 16:23:06 +0000372 return False
373 except OSError as err:
374 if err.errno != errno.EINTR:
375 raise
376 return True
Christian Heimes8640e742008-02-23 16:23:06 +0000377
378 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200379 # If a signal handler is installed and siginterrupt is not called
380 # at all, when that signal arrives, it interrupts a syscall that's in
381 # progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000382 i = self.readpipe_interrupted()
383 self.assertTrue(i)
384 # Arrival of the signal shouldn't have changed anything.
385 i = self.readpipe_interrupted()
386 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000387
388 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200389 # If a signal handler is installed and siginterrupt is called with
390 # a true value for the second argument, when that signal arrives, it
391 # interrupts a syscall that's in progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000392 signal.siginterrupt(self.signum, 1)
393 i = self.readpipe_interrupted()
394 self.assertTrue(i)
395 # Arrival of the signal shouldn't have changed anything.
396 i = self.readpipe_interrupted()
397 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000398
399 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200400 # If a signal handler is installed and siginterrupt is called with
401 # a false value for the second argument, when that signal arrives, it
402 # does not interrupt a syscall that's in progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000403 signal.siginterrupt(self.signum, 0)
404 i = self.readpipe_interrupted()
405 self.assertFalse(i)
406 # Arrival of the signal shouldn't have changed anything.
407 i = self.readpipe_interrupted()
408 self.assertFalse(i)
409
410
Brian Curtin3f004b12010-08-06 19:34:52 +0000411@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000412class ItimerTest(unittest.TestCase):
413 def setUp(self):
414 self.hndl_called = False
415 self.hndl_count = 0
416 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000417 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000418
419 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000420 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000421 if self.itimer is not None: # test_itimer_exc doesn't change this attr
422 # just ensure that itimer is stopped
423 signal.setitimer(self.itimer, 0)
424
425 def sig_alrm(self, *args):
426 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000427
428 def sig_vtalrm(self, *args):
429 self.hndl_called = True
430
431 if self.hndl_count > 3:
432 # it shouldn't be here, because it should have been disabled.
433 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
434 "timer.")
435 elif self.hndl_count == 3:
436 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
437 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000438
439 self.hndl_count += 1
440
Martin v. Löwis823725e2008-03-24 13:39:54 +0000441 def sig_prof(self, *args):
442 self.hndl_called = True
443 signal.setitimer(signal.ITIMER_PROF, 0)
444
Martin v. Löwis823725e2008-03-24 13:39:54 +0000445 def test_itimer_exc(self):
446 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
447 # defines it ?
448 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000449 # Negative times are treated as zero on some platforms.
450 if 0:
451 self.assertRaises(signal.ItimerError,
452 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000453
454 def test_itimer_real(self):
455 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000456 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000457 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000458 self.assertEqual(self.hndl_called, True)
459
R. David Murray44546f82010-04-21 01:59:28 +0000460 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000461 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
462 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000463 def test_itimer_virtual(self):
464 self.itimer = signal.ITIMER_VIRTUAL
465 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
466 signal.setitimer(self.itimer, 0.3, 0.2)
467
Mark Dickinson78373472009-10-31 10:39:21 +0000468 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000469 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000470 # use up some virtual time by doing real work
471 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000472 if signal.getitimer(self.itimer) == (0.0, 0.0):
473 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000474 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000475 self.skipTest("timeout: likely cause: machine too slow or load too "
476 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000477
478 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000479 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000480 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000481 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000482
R. David Murray44546f82010-04-21 01:59:28 +0000483 # Issue 3864, unknown if this affects earlier versions of freebsd also
484 @unittest.skipIf(sys.platform=='freebsd6',
485 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000486 def test_itimer_prof(self):
487 self.itimer = signal.ITIMER_PROF
488 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000489 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000490
Mark Dickinson78373472009-10-31 10:39:21 +0000491 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000492 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000493 # do some work
494 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000495 if signal.getitimer(self.itimer) == (0.0, 0.0):
496 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000497 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000498 self.skipTest("timeout: likely cause: machine too slow or load too "
499 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000500
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000501 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000502 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000503 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000504 self.assertEqual(self.hndl_called, True)
505
Victor Stinnera9293352011-04-30 15:21:58 +0200506
Victor Stinner35b300c2011-05-04 13:20:35 +0200507class PendingSignalsTests(unittest.TestCase):
508 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200509 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
510 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200511 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200512 def setUp(self):
513 self.has_pthread_kill = hasattr(signal, 'pthread_kill')
514
Victor Stinner35b300c2011-05-04 13:20:35 +0200515 def handler(self, signum, frame):
516 1/0
517
518 def read_sigmask(self):
519 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
520
Victor Stinnerb3e72192011-05-08 01:46:11 +0200521 def can_test_blocked_signals(self, skip):
522 """
523 Check if a blocked signal can be raised to the main thread without
524 calling its signal handler. We need pthread_kill() or exactly one
525 thread (the main thread).
Victor Stinnera9293352011-04-30 15:21:58 +0200526
Victor Stinnerb3e72192011-05-08 01:46:11 +0200527 Return True if it's possible. Otherwise, return False and print a
528 warning if skip is False, or raise a SkipTest exception if skip is
529 True.
530 """
531 if self.has_pthread_kill:
532 return True
Victor Stinnera9293352011-04-30 15:21:58 +0200533
Victor Stinnerf44ce872011-05-03 17:20:31 +0200534 # The fault handler timeout thread masks all signals. If the main
535 # thread masks also SIGUSR1, all threads mask this signal. In this
536 # case, if we send SIGUSR1 to the process, the signal is pending in the
537 # main or the faulthandler timeout thread. Unblock SIGUSR1 in the main
538 # thread calls the signal handler only if the signal is pending for the
Victor Stinnerb3e72192011-05-08 01:46:11 +0200539 # main thread. Stop the faulthandler timeout thread to workaround this
540 # problem.
541 import faulthandler
Victor Stinnerf44ce872011-05-03 17:20:31 +0200542 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner2d4a91e2011-05-03 14:11:22 +0200543
Victor Stinnerb3e72192011-05-08 01:46:11 +0200544 # Issue #11998: The _tkinter module loads the Tcl library which
545 # creates a thread waiting events in select(). This thread receives
546 # signals blocked by all other threads. We cannot test blocked
547 # signals
548 if '_tkinter' in sys.modules:
549 message = ("_tkinter is loaded and pthread_kill() is missing, "
550 "cannot test blocked signals (issue #11998)")
551 if skip:
552 self.skipTest(message)
553 else:
554 print("WARNING: %s" % message)
555 return False
556 return True
557
558 def kill(self, signum):
559 if self.has_pthread_kill:
560 tid = threading.current_thread().ident
561 signal.pthread_kill(tid, signum)
562 else:
563 pid = os.getpid()
564 os.kill(pid, signum)
565
566 @unittest.skipUnless(hasattr(signal, 'sigpending'),
567 'need signal.sigpending()')
568 def test_sigpending_empty(self):
569 self.assertEqual(signal.sigpending(), set())
570
571 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
572 'need signal.pthread_sigmask()')
573 @unittest.skipUnless(hasattr(signal, 'sigpending'),
574 'need signal.sigpending()')
575 def test_sigpending(self):
576 self.can_test_blocked_signals(True)
577
578 signum = signal.SIGUSR1
579 old_handler = signal.signal(signum, self.handler)
580 self.addCleanup(signal.signal, signum, old_handler)
581
582 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
583 self.kill(signum)
584 self.assertEqual(signal.sigpending(), {signum})
585 with self.assertRaises(ZeroDivisionError):
586 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
587
588 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
589 'need signal.pthread_kill()')
590 def test_pthread_kill(self):
591 signum = signal.SIGUSR1
592 current = threading.current_thread().ident
593
594 old_handler = signal.signal(signum, self.handler)
595 self.addCleanup(signal.signal, signum, old_handler)
596
597 with self.assertRaises(ZeroDivisionError):
598 signal.pthread_kill(current, signum)
599
600 @unittest.skipUnless(hasattr(signal, 'sigwait'),
601 'need signal.sigwait()')
602 def test_sigwait(self):
603 old_handler = signal.signal(signal.SIGALRM, self.handler)
604 self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
605
606 signal.alarm(1)
607 self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)
608
609 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
610 'need signal.pthread_sigmask()')
611 def test_pthread_sigmask_arguments(self):
612 self.assertRaises(TypeError, signal.pthread_sigmask)
613 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
614 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
615 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
616
617 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
618 'need signal.pthread_sigmask()')
619 def test_pthread_sigmask(self):
620 test_blocked_signals = self.can_test_blocked_signals(False)
621 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200622
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200623 # Install our signal handler
Victor Stinner35b300c2011-05-04 13:20:35 +0200624 old_handler = signal.signal(signum, self.handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200625 self.addCleanup(signal.signal, signum, old_handler)
626
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200627 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200628 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
629 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200630 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200631 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200632
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200633 # Block and then raise SIGUSR1. The signal is blocked: the signal
634 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200635 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerb3e72192011-05-08 01:46:11 +0200636 if test_blocked_signals:
637 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200638
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200639 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200640 blocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200641 self.assertIn(signum, blocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200642 self.assertEqual(old_mask ^ blocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200643
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200644 # Unblock SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200645 if test_blocked_signals:
Victor Stinner6fd49e12011-05-04 12:38:03 +0200646 with self.assertRaises(ZeroDivisionError):
647 # unblock the pending signal calls immediatly the signal handler
648 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
649 else:
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200650 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
651 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200652 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200653
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200654 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200655 unblocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200656 self.assertNotIn(signum, unblocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200657 self.assertEqual(blocked ^ unblocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200658 self.assertSequenceEqual(old_mask, unblocked)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200659 # Finally, restore the previous signal handler and the signal mask
Victor Stinnera9293352011-04-30 15:21:58 +0200660
661
Thomas Woutersed03b412007-08-28 21:37:11 +0000662def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100663 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200664 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100665 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200666 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200667 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100668 finally:
669 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000670
671
672if __name__ == "__main__":
673 test_main()