blob: ede6545397f868dda4f2476de135789536a597ff [file] [log] [blame]
Victor Stinner8d642482011-07-01 15:24:50 +02001import errno
Christian Heimescc47b052008-03-25 14:56:36 +00002import gc
Victor Stinner8d642482011-07-01 15:24:50 +02003import os
Christian Heimes4fbc72b2008-03-22 00:47:35 +00004import pickle
5import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00006import signal
Christian Heimes4fbc72b2008-03-22 00:47:35 +00007import subprocess
Victor Stinner8d642482011-07-01 15:24:50 +02008import sys
9import time
Christian Heimes4fbc72b2008-03-22 00:47:35 +000010import traceback
Victor Stinner8d642482011-07-01 15:24:50 +020011import unittest
12from test import support
13from contextlib import closing
14from test.script_helper import spawn_python
Christian Heimesc06950e2008-02-28 21:17:00 +000015
Brian Curtin912443c2010-09-06 16:10:04 +000016if sys.platform in ('os2', 'riscos'):
17 raise unittest.SkipTest("Can't test signal on %s" % sys.platform)
Christian Heimesc06950e2008-02-28 21:17:00 +000018
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000019
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000020class HandlerBCalled(Exception):
21 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000022
Christian Heimes4fbc72b2008-03-22 00:47:35 +000023
24def exit_subprocess():
25 """Use os._exit(0) to exit the current subprocess.
26
27 Otherwise, the test catches the SystemExit and continues executing
28 in parallel with the original test, so you wind up with an
29 exponential number of tests running concurrently.
30 """
31 os._exit(0)
32
33
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000034def ignoring_eintr(__func, *args, **kwargs):
35 try:
36 return __func(*args, **kwargs)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +000037 except EnvironmentError as e:
38 if e.errno != errno.EINTR:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000039 raise
40 return None
41
42
Brian Curtin3f004b12010-08-06 19:34:52 +000043@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +000044class InterProcessSignalTests(unittest.TestCase):
45 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000046
Christian Heimescc47b052008-03-25 14:56:36 +000047 def setUp(self):
48 self.using_gc = gc.isenabled()
49 gc.disable()
50
51 def tearDown(self):
52 if self.using_gc:
53 gc.enable()
54
Christian Heimes5e696852008-04-09 08:37:03 +000055 def format_frame(self, frame, limit=None):
56 return ''.join(traceback.format_stack(frame, limit=limit))
57
58 def handlerA(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000059 self.a_called = True
Benjamin Petersonee8712c2008-05-20 21:35:26 +000060 if support.verbose:
Christian Heimes5e696852008-04-09 08:37:03 +000061 print("handlerA invoked from signal %s at:\n%s" % (
62 signum, self.format_frame(frame, limit=1)))
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000063
Christian Heimes5e696852008-04-09 08:37:03 +000064 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000065 self.b_called = True
Benjamin Petersonee8712c2008-05-20 21:35:26 +000066 if support.verbose:
Christian Heimes5e696852008-04-09 08:37:03 +000067 print ("handlerB invoked from signal %s at:\n%s" % (
68 signum, self.format_frame(frame, limit=1)))
69 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000070
Christian Heimes4fbc72b2008-03-22 00:47:35 +000071 def wait(self, child):
72 """Wait for child to finish, ignoring EINTR."""
73 while True:
74 try:
75 child.wait()
76 return
77 except OSError as e:
78 if e.errno != errno.EINTR:
79 raise
Fred Drake004d5e62000-10-23 17:22:08 +000080
Christian Heimes4fbc72b2008-03-22 00:47:35 +000081 def run_test(self):
82 # Install handlers. This function runs in a sub-process, so we
83 # don't worry about re-setting the default handlers.
84 signal.signal(signal.SIGHUP, self.handlerA)
85 signal.signal(signal.SIGUSR1, self.handlerB)
86 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
87 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000088
Christian Heimes4fbc72b2008-03-22 00:47:35 +000089 # Variables the signals will modify:
90 self.a_called = False
91 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000092
Christian Heimes4fbc72b2008-03-22 00:47:35 +000093 # Let the sub-processes know who to send signals to.
94 pid = os.getpid()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000095 if support.verbose:
Thomas Woutersed03b412007-08-28 21:37:11 +000096 print("test runner's pid is", pid)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000097
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000098 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
99 if child:
100 self.wait(child)
101 if not self.a_called:
102 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000103 self.assertTrue(self.a_called)
104 self.assertFalse(self.b_called)
105 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000106
Christian Heimes5e696852008-04-09 08:37:03 +0000107 # Make sure the signal isn't delivered while the previous
108 # Popen object is being destroyed, because __del__ swallows
109 # exceptions.
110 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000111 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000112 child = subprocess.Popen(['kill', '-USR1', str(pid)])
113 # This wait should be interrupted by the signal's exception.
114 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000115 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000116 self.fail('HandlerBCalled exception not thrown')
117 except HandlerBCalled:
118 self.assertTrue(self.b_called)
119 self.assertFalse(self.a_called)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000120 if support.verbose:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000121 print("HandlerBCalled exception caught")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000122
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000123 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
124 if child:
125 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000126
127 try:
128 signal.alarm(1)
129 # The race condition in pause doesn't matter in this case,
130 # since alarm is going to raise a KeyboardException, which
131 # will skip the call.
132 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000133 # But if another signal arrives before the alarm, pause
134 # may return early.
135 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000136 except KeyboardInterrupt:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000137 if support.verbose:
Thomas Woutersed03b412007-08-28 21:37:11 +0000138 print("KeyboardInterrupt (the alarm() went off)")
Thomas Woutersed03b412007-08-28 21:37:11 +0000139 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000140 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000141 traceback.format_exc())
142 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000143 self.fail("pause returned of its own accord, and the signal"
144 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000145
R. David Murray44546f82010-04-21 01:59:28 +0000146 # Issue 3864, unknown if this affects earlier versions of freebsd also
147 @unittest.skipIf(sys.platform=='freebsd6',
148 'inter process signals not reliable (do not mix well with threading) '
149 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000150 def test_main(self):
151 # This function spawns a child process to insulate the main
152 # test-running process from all the signals. It then
153 # communicates with that child process over a pipe and
154 # re-raises information about any exceptions the child
155 # throws. The real work happens in self.run_test().
156 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000157 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
158 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000159 child = os.fork()
160 if child == 0:
161 # In the child process; run the test and report results
162 # through the pipe.
163 try:
164 done_r.close()
165 # Have to close done_w again here because
166 # exit_subprocess() will skip the enclosing with block.
167 with closing(done_w):
168 try:
169 self.run_test()
170 except:
171 pickle.dump(traceback.format_exc(), done_w)
172 else:
173 pickle.dump(None, done_w)
174 except:
175 print('Uh oh, raised from pickle.')
176 traceback.print_exc()
177 finally:
178 exit_subprocess()
179
180 done_w.close()
181 # Block for up to MAX_DURATION seconds for the test to finish.
182 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
183 if done_r in r:
184 tb = pickle.load(done_r)
185 if tb:
186 self.fail(tb)
187 else:
188 os.kill(child, signal.SIGKILL)
189 self.fail('Test deadlocked after %d seconds.' %
190 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000191
192
Brian Curtin3f004b12010-08-06 19:34:52 +0000193@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Thomas Woutersed03b412007-08-28 21:37:11 +0000194class BasicSignalTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000195 def trivial_signal_handler(self, *args):
196 pass
197
Thomas Woutersed03b412007-08-28 21:37:11 +0000198 def test_out_of_range_signal_number_raises_error(self):
199 self.assertRaises(ValueError, signal.getsignal, 4242)
200
Thomas Woutersed03b412007-08-28 21:37:11 +0000201 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000202 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000203
204 def test_setting_signal_handler_to_none_raises_error(self):
205 self.assertRaises(TypeError, signal.signal,
206 signal.SIGUSR1, None)
207
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000208 def test_getsignal(self):
209 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000210 self.assertEqual(signal.getsignal(signal.SIGHUP),
211 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000212 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000213 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000214
215
Brian Curtin3f004b12010-08-06 19:34:52 +0000216@unittest.skipUnless(sys.platform == "win32", "Windows specific")
217class WindowsSignalTests(unittest.TestCase):
218 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000219 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000220 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +0000221 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
222 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
223 signal.SIGTERM):
224 # Set and then reset a handler for signals that work on windows
225 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin3f004b12010-08-06 19:34:52 +0000226
227 with self.assertRaises(ValueError):
228 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000229
230 with self.assertRaises(ValueError):
231 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000232
233
234@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000235class WakeupSignalTests(unittest.TestCase):
236 TIMEOUT_FULL = 10
237 TIMEOUT_HALF = 5
238
239 def test_wakeup_fd_early(self):
240 import select
241
242 signal.alarm(1)
243 before_time = time.time()
244 # We attempt to get a signal during the sleep,
245 # before select is called
246 time.sleep(self.TIMEOUT_FULL)
247 mid_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000248 self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000249 select.select([self.read], [], [], self.TIMEOUT_FULL)
250 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000251 self.assertTrue(after_time - mid_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000252
253 def test_wakeup_fd_during(self):
254 import select
255
256 signal.alarm(1)
257 before_time = time.time()
258 # We attempt to get a signal during the select call
259 self.assertRaises(select.error, select.select,
260 [self.read], [], [], self.TIMEOUT_FULL)
261 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000262 self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000263
264 def setUp(self):
265 import fcntl
266
267 self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
268 self.read, self.write = os.pipe()
269 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
270 flags = flags | os.O_NONBLOCK
271 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
272 self.old_wakeup = signal.set_wakeup_fd(self.write)
273
274 def tearDown(self):
275 signal.set_wakeup_fd(self.old_wakeup)
276 os.close(self.read)
277 os.close(self.write)
278 signal.signal(signal.SIGALRM, self.alrm)
279
Brian Curtin3f004b12010-08-06 19:34:52 +0000280@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000281class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000282
Victor Stinner8d642482011-07-01 15:24:50 +0200283 def readpipe_interrupted(self, interrupt):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000284 """Perform a read during which a signal will arrive. Return True if the
285 read is interrupted by the signal and raises an exception. Return False
286 if it returns normally.
287 """
Victor Stinner8d642482011-07-01 15:24:50 +0200288 class Timeout(Exception):
289 pass
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000290
Victor Stinner8d642482011-07-01 15:24:50 +0200291 # use a subprocess to have only one thread, to have a timeout on the
292 # blocking read and to not touch signal handling in this process
293 code = """if 1:
294 import errno
295 import os
296 import signal
297 import sys
Christian Heimes8640e742008-02-23 16:23:06 +0000298
Victor Stinner8d642482011-07-01 15:24:50 +0200299 interrupt = %r
300 r, w = os.pipe()
301
302 def handler(signum, frame):
303 pass
304
Victor Stinner8d642482011-07-01 15:24:50 +0200305 signal.signal(signal.SIGALRM, handler)
306 if interrupt is not None:
307 signal.siginterrupt(signal.SIGALRM, interrupt)
308
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200309 print("ready")
310 sys.stdout.flush()
311
Victor Stinner8d642482011-07-01 15:24:50 +0200312 # run the test twice
313 for loop in range(2):
314 # send a SIGALRM in a second (during the read)
315 signal.alarm(1)
316 try:
317 # blocking call: read from a pipe without data
318 os.read(r, 1)
319 except OSError as err:
320 if err.errno != errno.EINTR:
321 raise
322 else:
323 sys.exit(2)
324 sys.exit(3)
325 """ % (interrupt,)
326 with spawn_python('-c', code) as process:
Christian Heimes8640e742008-02-23 16:23:06 +0000327 try:
Victor Stinner8d642482011-07-01 15:24:50 +0200328 # wait until the child process is loaded and has started
329 first_line = process.stdout.readline()
Christian Heimes8640e742008-02-23 16:23:06 +0000330
Victor Stinnerdfde0d42011-07-01 15:58:39 +0200331 # Wait the process with a timeout of 5 seconds
332 timeout = time.time() + 5.0
Victor Stinner8d642482011-07-01 15:24:50 +0200333 while True:
334 if timeout < time.time():
335 raise Timeout()
336 status = process.poll()
337 if status is not None:
338 break
339 time.sleep(0.1)
Christian Heimes8640e742008-02-23 16:23:06 +0000340
Victor Stinner8d642482011-07-01 15:24:50 +0200341 stdout, stderr = process.communicate()
342 except Timeout:
343 process.kill()
Christian Heimes8640e742008-02-23 16:23:06 +0000344 return False
Victor Stinner8d642482011-07-01 15:24:50 +0200345 else:
346 stdout = first_line + stdout
347 exitcode = process.wait()
348 if exitcode not in (2, 3):
349 raise Exception("Child error (exit code %s): %s"
350 % (exitcode, stdout))
351 return (exitcode == 3)
Christian Heimes8640e742008-02-23 16:23:06 +0000352
353 def test_without_siginterrupt(self):
Victor Stinner8d642482011-07-01 15:24:50 +0200354 # If a signal handler is installed and siginterrupt is not called
355 # at all, when that signal arrives, it interrupts a syscall that's in
356 # progress.
357 interrupted = self.readpipe_interrupted(None)
358 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000359
360 def test_siginterrupt_on(self):
Victor Stinner8d642482011-07-01 15:24:50 +0200361 # If a signal handler is installed and siginterrupt is called with
362 # a true value for the second argument, when that signal arrives, it
363 # interrupts a syscall that's in progress.
364 interrupted = self.readpipe_interrupted(True)
365 self.assertTrue(interrupted)
Christian Heimes8640e742008-02-23 16:23:06 +0000366
367 def test_siginterrupt_off(self):
Victor Stinner8d642482011-07-01 15:24:50 +0200368 # If a signal handler is installed and siginterrupt is called with
369 # a false value for the second argument, when that signal arrives, it
370 # does not interrupt a syscall that's in progress.
371 interrupted = self.readpipe_interrupted(False)
372 self.assertFalse(interrupted)
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000373
374
Brian Curtin3f004b12010-08-06 19:34:52 +0000375@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000376class ItimerTest(unittest.TestCase):
377 def setUp(self):
378 self.hndl_called = False
379 self.hndl_count = 0
380 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000381 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000382
383 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000384 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000385 if self.itimer is not None: # test_itimer_exc doesn't change this attr
386 # just ensure that itimer is stopped
387 signal.setitimer(self.itimer, 0)
388
389 def sig_alrm(self, *args):
390 self.hndl_called = True
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000391 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000392 print("SIGALRM handler invoked", args)
393
394 def sig_vtalrm(self, *args):
395 self.hndl_called = True
396
397 if self.hndl_count > 3:
398 # it shouldn't be here, because it should have been disabled.
399 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
400 "timer.")
401 elif self.hndl_count == 3:
402 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
403 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000404 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000405 print("last SIGVTALRM handler call")
406
407 self.hndl_count += 1
408
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000409 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000410 print("SIGVTALRM handler invoked", args)
411
412 def sig_prof(self, *args):
413 self.hndl_called = True
414 signal.setitimer(signal.ITIMER_PROF, 0)
415
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000416 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000417 print("SIGPROF handler invoked", args)
418
419 def test_itimer_exc(self):
420 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
421 # defines it ?
422 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000423 # Negative times are treated as zero on some platforms.
424 if 0:
425 self.assertRaises(signal.ItimerError,
426 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000427
428 def test_itimer_real(self):
429 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000430 signal.setitimer(self.itimer, 1.0)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000431 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000432 print("\ncall pause()...")
433 signal.pause()
434
435 self.assertEqual(self.hndl_called, True)
436
R. David Murray44546f82010-04-21 01:59:28 +0000437 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000438 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
439 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000440 def test_itimer_virtual(self):
441 self.itimer = signal.ITIMER_VIRTUAL
442 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
443 signal.setitimer(self.itimer, 0.3, 0.2)
444
Mark Dickinson78373472009-10-31 10:39:21 +0000445 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000446 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000447 # use up some virtual time by doing real work
448 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000449 if signal.getitimer(self.itimer) == (0.0, 0.0):
450 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000451 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000452 self.skipTest("timeout: likely cause: machine too slow or load too "
453 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000454
455 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000456 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000457 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000458 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000459
R. David Murray44546f82010-04-21 01:59:28 +0000460 # Issue 3864, unknown if this affects earlier versions of freebsd also
461 @unittest.skipIf(sys.platform=='freebsd6',
462 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000463 def test_itimer_prof(self):
464 self.itimer = signal.ITIMER_PROF
465 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000466 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000467
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 Dickinson78373472009-10-31 10:39:21 +0000470 # do some 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_prof 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
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000478 # profiling 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))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000480 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000481 self.assertEqual(self.hndl_called, True)
482
Thomas Woutersed03b412007-08-28 21:37:11 +0000483def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100484 try:
485 support.run_unittest(BasicSignalTests, InterProcessSignalTests,
486 WakeupSignalTests, SiginterruptTest,
487 ItimerTest, WindowsSignalTests)
488 finally:
489 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000490
491
492if __name__ == "__main__":
493 test_main()