blob: ae5b586b28275d368a726fa96217ab8bfda0562e [file] [log] [blame]
Georg Brandl9f2b93e2007-08-24 18:07:52 +00001import unittest
2from test import test_support
Jeffrey Yasskincf26f542008-03-21 05:02:44 +00003from contextlib import closing, nested
Neal Norwitzbb89e682008-03-25 07:00:39 +00004import gc
Jeffrey Yasskincf26f542008-03-21 05:02:44 +00005import pickle
6import select
Guido van Rossum4f17e3e1995-03-16 15:07:38 +00007import signal
Jeffrey Yasskin413f5882008-03-21 18:25:06 +00008import subprocess
Jeffrey Yasskincf26f542008-03-21 05:02:44 +00009import traceback
Christian Heimesacfd8ed2008-02-28 21:00:45 +000010import sys, os, time, errno
11
12if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos':
13 raise test_support.TestSkipped("Can't test signal on %s" % \
14 sys.platform)
15
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000016
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000017class HandlerBCalled(Exception):
18 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000019
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000020
21def exit_subprocess():
22 """Use os._exit(0) to exit the current subprocess.
23
24 Otherwise, the test catches the SystemExit and continues executing
25 in parallel with the original test, so you wind up with an
26 exponential number of tests running concurrently.
27 """
28 os._exit(0)
29
30
Jeffrey Yasskinab561312008-04-02 04:07:44 +000031def ignoring_eintr(__func, *args, **kwargs):
32 try:
33 return __func(*args, **kwargs)
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +000034 except EnvironmentError as e:
Jeffrey Yasskine71d8122008-04-04 16:48:19 +000035 if e.errno != errno.EINTR:
Jeffrey Yasskinab561312008-04-02 04:07:44 +000036 raise
37 return None
38
39
Georg Brandl9f2b93e2007-08-24 18:07:52 +000040class InterProcessSignalTests(unittest.TestCase):
41 MAX_DURATION = 20 # Entire test should last at most 20 sec.
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000042
Neal Norwitzbb89e682008-03-25 07:00:39 +000043 def setUp(self):
44 self.using_gc = gc.isenabled()
45 gc.disable()
46
47 def tearDown(self):
48 if self.using_gc:
49 gc.enable()
50
Jeffrey Yasskinee767772008-04-06 23:04:28 +000051 def format_frame(self, frame, limit=None):
52 return ''.join(traceback.format_stack(frame, limit=limit))
53
54 def handlerA(self, signum, frame):
Georg Brandl9f2b93e2007-08-24 18:07:52 +000055 self.a_called = True
56 if test_support.verbose:
Jeffrey Yasskinee767772008-04-06 23:04:28 +000057 print "handlerA invoked from signal %s at:\n%s" % (
58 signum, self.format_frame(frame, limit=1))
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000059
Jeffrey Yasskinee767772008-04-06 23:04:28 +000060 def handlerB(self, signum, frame):
Georg Brandl9f2b93e2007-08-24 18:07:52 +000061 self.b_called = True
62 if test_support.verbose:
Jeffrey Yasskinee767772008-04-06 23:04:28 +000063 print "handlerB invoked from signal %s at:\n%s" % (
64 signum, self.format_frame(frame, limit=1))
65 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000066
Jeffrey Yasskin413f5882008-03-21 18:25:06 +000067 def wait(self, child):
68 """Wait for child to finish, ignoring EINTR."""
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000069 while True:
70 try:
Jeffrey Yasskin413f5882008-03-21 18:25:06 +000071 child.wait()
Jeffrey Yasskin6cda88e2008-03-21 05:51:37 +000072 return
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000073 except OSError as e:
74 if e.errno != errno.EINTR:
75 raise
Fred Drake004d5e62000-10-23 17:22:08 +000076
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000077 def run_test(self):
78 # Install handlers. This function runs in a sub-process, so we
79 # don't worry about re-setting the default handlers.
80 signal.signal(signal.SIGHUP, self.handlerA)
81 signal.signal(signal.SIGUSR1, self.handlerB)
82 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
83 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000084
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000085 # Variables the signals will modify:
86 self.a_called = False
87 self.b_called = False
Tim Peters1742f332006-08-12 04:42:47 +000088
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000089 # Let the sub-processes know who to send signals to.
90 pid = os.getpid()
Georg Brandl9f2b93e2007-08-24 18:07:52 +000091 if test_support.verbose:
92 print "test runner's pid is", pid
Tim Peters1742f332006-08-12 04:42:47 +000093
Jeffrey Yasskinab561312008-04-02 04:07:44 +000094 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
95 if child:
96 self.wait(child)
97 if not self.a_called:
98 time.sleep(1) # Give the signal time to be delivered.
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000099 self.assertTrue(self.a_called)
100 self.assertFalse(self.b_called)
101 self.a_called = False
Tim Peters1742f332006-08-12 04:42:47 +0000102
Jeffrey Yasskinee767772008-04-06 23:04:28 +0000103 # Make sure the signal isn't delivered while the previous
104 # Popen object is being destroyed, because __del__ swallows
105 # exceptions.
106 del child
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000107 try:
Jeffrey Yasskin413f5882008-03-21 18:25:06 +0000108 child = subprocess.Popen(['kill', '-USR1', str(pid)])
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000109 # This wait should be interrupted by the signal's exception.
110 self.wait(child)
Jeffrey Yasskinab561312008-04-02 04:07:44 +0000111 time.sleep(1) # Give the signal time to be delivered.
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000112 self.fail('HandlerBCalled exception not thrown')
113 except HandlerBCalled:
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000114 self.assertTrue(self.b_called)
115 self.assertFalse(self.a_called)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000116 if test_support.verbose:
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000117 print "HandlerBCalled exception caught"
Neal Norwitzec3c5e32006-07-30 19:18:38 +0000118
Jeffrey Yasskinab561312008-04-02 04:07:44 +0000119 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
120 if child:
121 self.wait(child) # Nothing should happen.
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000122
123 try:
124 signal.alarm(1)
125 # The race condition in pause doesn't matter in this case,
126 # since alarm is going to raise a KeyboardException, which
127 # will skip the call.
128 signal.pause()
Jeffrey Yasskinab561312008-04-02 04:07:44 +0000129 # But if another signal arrives before the alarm, pause
130 # may return early.
131 time.sleep(1)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000132 except KeyboardInterrupt:
133 if test_support.verbose:
134 print "KeyboardInterrupt (the alarm() went off)"
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000135 except:
Jeffrey Yasskinab561312008-04-02 04:07:44 +0000136 self.fail("Some other exception woke us from pause: %s" %
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000137 traceback.format_exc())
138 else:
Jeffrey Yasskinab561312008-04-02 04:07:44 +0000139 self.fail("pause returned of its own accord, and the signal"
140 " didn't arrive after another second.")
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000141
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000142 def test_main(self):
R. David Murray12c5fbb2010-04-21 01:41:41 +0000143 # Issue 3864, unknown if this affects earlier versions of freebsd also
Stefan Krah312bded2010-06-03 16:04:47 +0000144 if sys.platform=='freebsd6':
145 if test_support.verbose:
146 sys.stderr.write('skipping -- inter process signals not '
147 'reliable (do not mix well with threading) on freebsd6\n')
R. David Murray12c5fbb2010-04-21 01:41:41 +0000148 return
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000149 # This function spawns a child process to insulate the main
150 # test-running process from all the signals. It then
151 # communicates with that child process over a pipe and
152 # re-raises information about any exceptions the child
153 # throws. The real work happens in self.run_test().
154 os_done_r, os_done_w = os.pipe()
155 with nested(closing(os.fdopen(os_done_r)),
156 closing(os.fdopen(os_done_w, 'w'))) as (done_r, done_w):
157 child = os.fork()
158 if child == 0:
159 # In the child process; run the test and report results
160 # through the pipe.
161 try:
162 done_r.close()
163 # Have to close done_w again here because
164 # exit_subprocess() will skip the enclosing with block.
165 with closing(done_w):
166 try:
167 self.run_test()
168 except:
169 pickle.dump(traceback.format_exc(), done_w)
170 else:
171 pickle.dump(None, done_w)
172 except:
173 print 'Uh oh, raised from pickle.'
174 traceback.print_exc()
175 finally:
176 exit_subprocess()
177
178 done_w.close()
179 # Block for up to MAX_DURATION seconds for the test to finish.
180 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
181 if done_r in r:
182 tb = pickle.load(done_r)
183 if tb:
184 self.fail(tb)
185 else:
186 os.kill(child, signal.SIGKILL)
187 self.fail('Test deadlocked after %d seconds.' %
188 self.MAX_DURATION)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000189
190
191class BasicSignalTests(unittest.TestCase):
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000192 def trivial_signal_handler(self, *args):
193 pass
194
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000195 def test_out_of_range_signal_number_raises_error(self):
196 self.assertRaises(ValueError, signal.getsignal, 4242)
197
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000198 self.assertRaises(ValueError, signal.signal, 4242,
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000199 self.trivial_signal_handler)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000200
201 def test_setting_signal_handler_to_none_raises_error(self):
202 self.assertRaises(TypeError, signal.signal,
203 signal.SIGUSR1, None)
204
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000205 def test_getsignal(self):
206 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
207 self.assertEquals(signal.getsignal(signal.SIGHUP),
208 self.trivial_signal_handler)
209 signal.signal(signal.SIGHUP, hup)
210 self.assertEquals(signal.getsignal(signal.SIGHUP), hup)
211
212
Guido van Rossum02de8972007-12-19 19:41:06 +0000213class WakeupSignalTests(unittest.TestCase):
214 TIMEOUT_FULL = 10
215 TIMEOUT_HALF = 5
216
217 def test_wakeup_fd_early(self):
218 import select
219
220 signal.alarm(1)
221 before_time = time.time()
222 # We attempt to get a signal during the sleep,
223 # before select is called
224 time.sleep(self.TIMEOUT_FULL)
225 mid_time = time.time()
226 self.assert_(mid_time - before_time < self.TIMEOUT_HALF)
227 select.select([self.read], [], [], self.TIMEOUT_FULL)
228 after_time = time.time()
229 self.assert_(after_time - mid_time < self.TIMEOUT_HALF)
230
231 def test_wakeup_fd_during(self):
232 import select
233
234 signal.alarm(1)
235 before_time = time.time()
236 # We attempt to get a signal during the select call
237 self.assertRaises(select.error, select.select,
238 [self.read], [], [], self.TIMEOUT_FULL)
239 after_time = time.time()
240 self.assert_(after_time - before_time < self.TIMEOUT_HALF)
241
242 def setUp(self):
243 import fcntl
244
245 self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
246 self.read, self.write = os.pipe()
247 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
248 flags = flags | os.O_NONBLOCK
249 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
250 self.old_wakeup = signal.set_wakeup_fd(self.write)
251
252 def tearDown(self):
253 signal.set_wakeup_fd(self.old_wakeup)
254 os.close(self.read)
255 os.close(self.write)
256 signal.signal(signal.SIGALRM, self.alrm)
257
Facundo Batista7e251e82008-02-23 15:07:35 +0000258class SiginterruptTest(unittest.TestCase):
259 signum = signal.SIGUSR1
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000260
261 def setUp(self):
262 """Install a no-op signal handler that can be set to allow
263 interrupts or not, and arrange for the original signal handler to be
264 re-installed when the test is finished.
265 """
266 self._cleanups = []
267 oldhandler = signal.signal(self.signum, lambda x,y: None)
268 self.addCleanup(signal.signal, self.signum, oldhandler)
269
270
271 def tearDown(self):
272 """Run any cleanup functions which have been registered.
273 """
274 for (f, a) in self._cleanups:
275 f(*a)
276
277
278 def addCleanup(self, f, *a):
279 """Register a function to be called at the end of the test method
280 run.
281 """
282 self._cleanups.append((f, a))
283
284
285 def readpipe_interrupted(self):
286 """Perform a read during which a signal will arrive. Return True if the
287 read is interrupted by the signal and raises an exception. Return False
288 if it returns normally.
289 """
290 # Create a pipe that can be used for the read. Also clean it up
291 # when the test is over, since nothing else will (but see below for
292 # the write end).
Facundo Batista7e251e82008-02-23 15:07:35 +0000293 r, w = os.pipe()
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000294 self.addCleanup(os.close, r)
295
296 # Create another process which can send a signal to this one to try
297 # to interrupt the read.
Facundo Batista7e251e82008-02-23 15:07:35 +0000298 ppid = os.getpid()
299 pid = os.fork()
300
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000301 if pid == 0:
302 # Child code: sleep to give the parent enough time to enter the
303 # read() call (there's a race here, but it's really tricky to
304 # eliminate it); then signal the parent process. Also, sleep
305 # again to make it likely that the signal is delivered to the
306 # parent process before the child exits. If the child exits
307 # first, the write end of the pipe will be closed and the test
308 # is invalid.
Facundo Batista7e251e82008-02-23 15:07:35 +0000309 try:
310 time.sleep(0.2)
311 os.kill(ppid, self.signum)
312 time.sleep(0.2)
313 finally:
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000314 # No matter what, just exit as fast as possible now.
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000315 exit_subprocess()
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000316 else:
317 # Parent code.
318 # Make sure the child is eventually reaped, else it'll be a
319 # zombie for the rest of the test suite run.
320 self.addCleanup(os.waitpid, pid, 0)
Facundo Batista7e251e82008-02-23 15:07:35 +0000321
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000322 # Close the write end of the pipe. The child has a copy, so
323 # it's not really closed until the child exits. We need it to
324 # close when the child exits so that in the non-interrupt case
325 # the read eventually completes, otherwise we could just close
326 # it *after* the test.
Facundo Batista7e251e82008-02-23 15:07:35 +0000327 os.close(w)
328
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000329 # Try the read and report whether it is interrupted or not to
330 # the caller.
Facundo Batista7e251e82008-02-23 15:07:35 +0000331 try:
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000332 d = os.read(r, 1)
Facundo Batista7e251e82008-02-23 15:07:35 +0000333 return False
334 except OSError, err:
335 if err.errno != errno.EINTR:
336 raise
337 return True
Facundo Batista7e251e82008-02-23 15:07:35 +0000338
339 def test_without_siginterrupt(self):
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000340 """If a signal handler is installed and siginterrupt is not called
341 at all, when that signal arrives, it interrupts a syscall that's in
342 progress.
343 """
344 i = self.readpipe_interrupted()
345 self.assertTrue(i)
346 # Arrival of the signal shouldn't have changed anything.
347 i = self.readpipe_interrupted()
348 self.assertTrue(i)
Facundo Batista7e251e82008-02-23 15:07:35 +0000349
350 def test_siginterrupt_on(self):
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000351 """If a signal handler is installed and siginterrupt is called with
352 a true value for the second argument, when that signal arrives, it
353 interrupts a syscall that's in progress.
354 """
355 signal.siginterrupt(self.signum, 1)
356 i = self.readpipe_interrupted()
357 self.assertTrue(i)
358 # Arrival of the signal shouldn't have changed anything.
359 i = self.readpipe_interrupted()
360 self.assertTrue(i)
Facundo Batista7e251e82008-02-23 15:07:35 +0000361
362 def test_siginterrupt_off(self):
Jean-Paul Calderone0819b092010-05-08 21:11:28 +0000363 """If a signal handler is installed and siginterrupt is called with
364 a false value for the second argument, when that signal arrives, it
365 does not interrupt a syscall that's in progress.
366 """
367 signal.siginterrupt(self.signum, 0)
368 i = self.readpipe_interrupted()
369 self.assertFalse(i)
370 # Arrival of the signal shouldn't have changed anything.
371 i = self.readpipe_interrupted()
372 self.assertFalse(i)
373
374
Guido van Rossum02de8972007-12-19 19:41:06 +0000375
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000376class ItimerTest(unittest.TestCase):
377 def setUp(self):
378 self.hndl_called = False
379 self.hndl_count = 0
380 self.itimer = None
Neal Norwitzbb89e682008-03-25 07:00:39 +0000381 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000382
383 def tearDown(self):
Neal Norwitzbb89e682008-03-25 07:00:39 +0000384 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwisaef18b12008-03-24 13:31:16 +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
391 if test_support.verbose:
392 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)
404 if test_support.verbose:
405 print("last SIGVTALRM handler call")
406
407 self.hndl_count += 1
408
409 if test_support.verbose:
410 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
416 if test_support.verbose:
417 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)
Neal Norwitzbb89e682008-03-25 07:00:39 +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öwisaef18b12008-03-24 13:31:16 +0000427
428 def test_itimer_real(self):
429 self.itimer = signal.ITIMER_REAL
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000430 signal.setitimer(self.itimer, 1.0)
431 if test_support.verbose:
432 print("\ncall pause()...")
433 signal.pause()
434
435 self.assertEqual(self.hndl_called, True)
436
437 def test_itimer_virtual(self):
R. David Murray12c5fbb2010-04-21 01:41:41 +0000438 # Issue 3864, unknown if this affects earlier versions of freebsd also
Stefan Krah312bded2010-06-03 16:04:47 +0000439 if sys.platform=='freebsd6':
440 if test_support.verbose:
441 sys.stderr.write('skipping -- itimer not reliable (does not '
442 'mix well with threading) on freebsd6\n')
R. David Murray12c5fbb2010-04-21 01:41:41 +0000443 return
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000444 self.itimer = signal.ITIMER_VIRTUAL
445 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
446 signal.setitimer(self.itimer, 0.3, 0.2)
447
Mark Dickinson265035e2009-10-31 10:37:15 +0000448 start_time = time.time()
Stefan Krah488fea32010-04-20 08:07:08 +0000449 while time.time() - start_time < 60.0:
Mark Dickinson5fab1692009-10-04 18:41:25 +0000450 # use up some virtual time by doing real work
451 _ = pow(12345, 67890, 10000019)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000452 if signal.getitimer(self.itimer) == (0.0, 0.0):
453 break # sig_vtalrm handler stopped this itimer
Stefan Krah488fea32010-04-20 08:07:08 +0000454 else: # Issue 8424
Stefan Krah686e56b2010-05-15 09:34:50 +0000455 sys.stderr.write("test_itimer_virtual: timeout: likely cause: "
Stefan Krah488fea32010-04-20 08:07:08 +0000456 "machine too slow or load too high.\n")
457 return
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000458
459 # virtual itimer should be (0.0, 0.0) now
460 self.assertEquals(signal.getitimer(self.itimer), (0.0, 0.0))
461 # and the handler should have been called
462 self.assertEquals(self.hndl_called, True)
463
464 def test_itimer_prof(self):
R. David Murray12c5fbb2010-04-21 01:41:41 +0000465 # Issue 3864, unknown if this affects earlier versions of freebsd also
Stefan Krah312bded2010-06-03 16:04:47 +0000466 if sys.platform=='freebsd6':
467 if test_support.verbose:
468 sys.stderr.write('skipping -- itimer not reliable (does not '
469 'mix well with threading) on freebsd6\n')
R. David Murray12c5fbb2010-04-21 01:41:41 +0000470 return
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000471 self.itimer = signal.ITIMER_PROF
472 signal.signal(signal.SIGPROF, self.sig_prof)
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +0000473 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000474
Mark Dickinson265035e2009-10-31 10:37:15 +0000475 start_time = time.time()
Stefan Krah488fea32010-04-20 08:07:08 +0000476 while time.time() - start_time < 60.0:
Mark Dickinson265035e2009-10-31 10:37:15 +0000477 # do some work
478 _ = pow(12345, 67890, 10000019)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000479 if signal.getitimer(self.itimer) == (0.0, 0.0):
480 break # sig_prof handler stopped this itimer
Stefan Krah488fea32010-04-20 08:07:08 +0000481 else: # Issue 8424
482 sys.stdout.write("test_itimer_prof: timeout: likely cause: "
483 "machine too slow or load too high.\n")
484 return
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000485
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +0000486 # profiling itimer should be (0.0, 0.0) now
487 self.assertEquals(signal.getitimer(self.itimer), (0.0, 0.0))
488 # and the handler should have been called
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000489 self.assertEqual(self.hndl_called, True)
490
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000491def test_main():
Guido van Rossum02de8972007-12-19 19:41:06 +0000492 test_support.run_unittest(BasicSignalTests, InterProcessSignalTests,
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000493 WakeupSignalTests, SiginterruptTest, ItimerTest)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000494
495
496if __name__ == "__main__":
497 test_main()