blob: 5f4f579a677c4124951b92dcd2d887f8ff6005ae [file] [log] [blame]
Georg Brandl9f2b93e2007-08-24 18:07:52 +00001import unittest
2from test import test_support
Georg Brandlc29863e2009-06-18 22:24:26 +00003from contextlib import closing
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
Brian Curtin84263332010-09-06 16:17:50 +000012if sys.platform in ('os2', 'riscos'):
13 raise unittest.SkipTest("Can't test signal on %s" % sys.platform)
Christian Heimesacfd8ed2008-02-28 21:00:45 +000014
Guido van Rossumcc5a91d1997-04-16 00:29:15 +000015
Armin Rigo8b2cbfd2004-08-07 21:27:43 +000016class HandlerBCalled(Exception):
17 pass
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000018
Jeffrey Yasskincf26f542008-03-21 05:02:44 +000019
20def exit_subprocess():
21 """Use os._exit(0) to exit the current subprocess.
22
23 Otherwise, the test catches the SystemExit and continues executing
24 in parallel with the original test, so you wind up with an
25 exponential number of tests running concurrently.
26 """
27 os._exit(0)
28
29
Jeffrey Yasskinab561312008-04-02 04:07:44 +000030def ignoring_eintr(__func, *args, **kwargs):
31 try:
32 return __func(*args, **kwargs)
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +000033 except EnvironmentError as e:
Jeffrey Yasskine71d8122008-04-04 16:48:19 +000034 if e.errno != errno.EINTR:
Jeffrey Yasskinab561312008-04-02 04:07:44 +000035 raise
36 return None
37
38
Brian Curtin24af0e92010-08-06 19:41:01 +000039@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
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.
Andrew Svetlov4bb142b2012-12-18 21:27:37 +0200112 self.fail('HandlerBCalled exception not raised')
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000113 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.")
Victor Stinner3604b232018-06-01 15:23:02 +0200141 finally:
142 signal.alarm(0)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000143
Stefan Krah68b4e012010-04-20 07:59:10 +0000144 # Issue 3864. Unknown if this affects earlier versions of freebsd also.
R. David Murraye0e8a872010-04-17 05:26:26 +0000145 @unittest.skipIf(sys.platform=='freebsd6',
146 'inter process signals not reliable (do not mix well with threading) '
147 'on freebsd6')
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000148 def test_main(self):
149 # 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
Andrew Svetlov4bb142b2012-12-18 21:27:37 +0200153 # raises. The real work happens in self.run_test().
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000154 os_done_r, os_done_w = os.pipe()
Georg Brandlc29863e2009-06-18 22:24:26 +0000155 with closing(os.fdopen(os_done_r)) as done_r, \
156 closing(os.fdopen(os_done_w, 'w')) as done_w:
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000157 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
Victor Stinner1460ce52017-08-22 16:51:09 +0200190 # read the exit status to not leak a zombie process
191 os.waitpid(child, 0)
192
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000193
Brian Curtin24af0e92010-08-06 19:41:01 +0000194@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000195class BasicSignalTests(unittest.TestCase):
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000196 def trivial_signal_handler(self, *args):
197 pass
198
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000199 def test_out_of_range_signal_number_raises_error(self):
200 self.assertRaises(ValueError, signal.getsignal, 4242)
201
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000202 self.assertRaises(ValueError, signal.signal, 4242,
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000203 self.trivial_signal_handler)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000204
205 def test_setting_signal_handler_to_none_raises_error(self):
206 self.assertRaises(TypeError, signal.signal,
207 signal.SIGUSR1, None)
208
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000209 def test_getsignal(self):
210 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti2623a372010-11-21 13:34:58 +0000211 self.assertEqual(signal.getsignal(signal.SIGHUP),
212 self.trivial_signal_handler)
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000213 signal.signal(signal.SIGHUP, hup)
Ezio Melotti2623a372010-11-21 13:34:58 +0000214 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000215
216
Brian Curtin24af0e92010-08-06 19:41:01 +0000217@unittest.skipUnless(sys.platform == "win32", "Windows specific")
218class WindowsSignalTests(unittest.TestCase):
219 def test_issue9324(self):
Brian Curtin1390dd72010-10-01 16:44:03 +0000220 # Updated for issue #10003, adding SIGBREAK
Brian Curtin24af0e92010-08-06 19:41:01 +0000221 handler = lambda x, y: None
Brian Curtin1390dd72010-10-01 16:44:03 +0000222 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
223 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
224 signal.SIGTERM):
225 # Set and then reset a handler for signals that work on windows
226 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin24af0e92010-08-06 19:41:01 +0000227
228 with self.assertRaises(ValueError):
229 signal.signal(-1, handler)
Brian Curtin9d310d32010-08-07 03:56:16 +0000230
231 with self.assertRaises(ValueError):
232 signal.signal(7, handler)
Brian Curtin24af0e92010-08-06 19:41:01 +0000233
234
Benjamin Peterson08e153a2013-01-18 00:10:24 -0500235class WakeupFDTests(unittest.TestCase):
236
237 def test_invalid_fd(self):
Benjamin Peterson2f78f0e2013-01-18 00:44:49 -0500238 fd = test_support.make_bad_fd()
Benjamin Peterson08e153a2013-01-18 00:10:24 -0500239 self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
240
241
Brian Curtin24af0e92010-08-06 19:41:01 +0000242@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Guido van Rossum02de8972007-12-19 19:41:06 +0000243class WakeupSignalTests(unittest.TestCase):
244 TIMEOUT_FULL = 10
245 TIMEOUT_HALF = 5
246
247 def test_wakeup_fd_early(self):
248 import select
249
250 signal.alarm(1)
Victor Stinner3604b232018-06-01 15:23:02 +0200251 try:
252 before_time = time.time()
253 # We attempt to get a signal during the sleep,
254 # before select is called
255 time.sleep(self.TIMEOUT_FULL)
256 mid_time = time.time()
257 finally:
258 signal.alarm(0)
259
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000260 self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
Guido van Rossum02de8972007-12-19 19:41:06 +0000261 select.select([self.read], [], [], self.TIMEOUT_FULL)
262 after_time = time.time()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000263 self.assertTrue(after_time - mid_time < self.TIMEOUT_HALF)
Guido van Rossum02de8972007-12-19 19:41:06 +0000264
265 def test_wakeup_fd_during(self):
266 import select
267
268 signal.alarm(1)
Victor Stinner3604b232018-06-01 15:23:02 +0200269 try:
270 before_time = time.time()
271 # We attempt to get a signal during the select call
272 self.assertRaises(select.error, select.select,
273 [self.read], [], [], self.TIMEOUT_FULL)
274 after_time = time.time()
275 finally:
276 signal.alarm(0)
277
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000278 self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
Guido van Rossum02de8972007-12-19 19:41:06 +0000279
280 def setUp(self):
281 import fcntl
282
283 self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
284 self.read, self.write = os.pipe()
285 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
286 flags = flags | os.O_NONBLOCK
287 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
288 self.old_wakeup = signal.set_wakeup_fd(self.write)
289
290 def tearDown(self):
291 signal.set_wakeup_fd(self.old_wakeup)
292 os.close(self.read)
293 os.close(self.write)
294 signal.signal(signal.SIGALRM, self.alrm)
295
Brian Curtin24af0e92010-08-06 19:41:01 +0000296@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Facundo Batista7e251e82008-02-23 15:07:35 +0000297class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000298
299 def setUp(self):
300 """Install a no-op signal handler that can be set to allow
301 interrupts or not, and arrange for the original signal handler to be
302 re-installed when the test is finished.
303 """
Brian Curtin24af0e92010-08-06 19:41:01 +0000304 self.signum = signal.SIGUSR1
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000305 oldhandler = signal.signal(self.signum, lambda x,y: None)
306 self.addCleanup(signal.signal, self.signum, oldhandler)
307
308 def readpipe_interrupted(self):
309 """Perform a read during which a signal will arrive. Return True if the
310 read is interrupted by the signal and raises an exception. Return False
311 if it returns normally.
312 """
313 # Create a pipe that can be used for the read. Also clean it up
314 # when the test is over, since nothing else will (but see below for
315 # the write end).
Facundo Batista7e251e82008-02-23 15:07:35 +0000316 r, w = os.pipe()
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000317 self.addCleanup(os.close, r)
318
319 # Create another process which can send a signal to this one to try
320 # to interrupt the read.
Facundo Batista7e251e82008-02-23 15:07:35 +0000321 ppid = os.getpid()
322 pid = os.fork()
323
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000324 if pid == 0:
325 # Child code: sleep to give the parent enough time to enter the
326 # read() call (there's a race here, but it's really tricky to
327 # eliminate it); then signal the parent process. Also, sleep
328 # again to make it likely that the signal is delivered to the
329 # parent process before the child exits. If the child exits
330 # first, the write end of the pipe will be closed and the test
331 # is invalid.
Facundo Batista7e251e82008-02-23 15:07:35 +0000332 try:
333 time.sleep(0.2)
334 os.kill(ppid, self.signum)
335 time.sleep(0.2)
336 finally:
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000337 # No matter what, just exit as fast as possible now.
Jeffrey Yasskincf26f542008-03-21 05:02:44 +0000338 exit_subprocess()
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000339 else:
340 # Parent code.
341 # Make sure the child is eventually reaped, else it'll be a
342 # zombie for the rest of the test suite run.
343 self.addCleanup(os.waitpid, pid, 0)
Facundo Batista7e251e82008-02-23 15:07:35 +0000344
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000345 # Close the write end of the pipe. The child has a copy, so
346 # it's not really closed until the child exits. We need it to
347 # close when the child exits so that in the non-interrupt case
348 # the read eventually completes, otherwise we could just close
349 # it *after* the test.
Facundo Batista7e251e82008-02-23 15:07:35 +0000350 os.close(w)
351
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000352 # Try the read and report whether it is interrupted or not to
353 # the caller.
Facundo Batista7e251e82008-02-23 15:07:35 +0000354 try:
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000355 d = os.read(r, 1)
Facundo Batista7e251e82008-02-23 15:07:35 +0000356 return False
357 except OSError, err:
358 if err.errno != errno.EINTR:
359 raise
360 return True
Facundo Batista7e251e82008-02-23 15:07:35 +0000361
362 def test_without_siginterrupt(self):
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000363 """If a signal handler is installed and siginterrupt is not called
364 at all, when that signal arrives, it interrupts a syscall that's in
365 progress.
366 """
367 i = self.readpipe_interrupted()
368 self.assertTrue(i)
369 # Arrival of the signal shouldn't have changed anything.
370 i = self.readpipe_interrupted()
371 self.assertTrue(i)
Facundo Batista7e251e82008-02-23 15:07:35 +0000372
373 def test_siginterrupt_on(self):
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000374 """If a signal handler is installed and siginterrupt is called with
375 a true value for the second argument, when that signal arrives, it
376 interrupts a syscall that's in progress.
377 """
378 signal.siginterrupt(self.signum, 1)
379 i = self.readpipe_interrupted()
380 self.assertTrue(i)
381 # Arrival of the signal shouldn't have changed anything.
382 i = self.readpipe_interrupted()
383 self.assertTrue(i)
Facundo Batista7e251e82008-02-23 15:07:35 +0000384
385 def test_siginterrupt_off(self):
Jean-Paul Calderonee54ddf12010-05-08 20:06:02 +0000386 """If a signal handler is installed and siginterrupt is called with
387 a false value for the second argument, when that signal arrives, it
388 does not interrupt a syscall that's in progress.
389 """
390 signal.siginterrupt(self.signum, 0)
391 i = self.readpipe_interrupted()
392 self.assertFalse(i)
393 # Arrival of the signal shouldn't have changed anything.
394 i = self.readpipe_interrupted()
395 self.assertFalse(i)
396
397
Brian Curtin24af0e92010-08-06 19:41:01 +0000398@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000399class ItimerTest(unittest.TestCase):
400 def setUp(self):
401 self.hndl_called = False
402 self.hndl_count = 0
403 self.itimer = None
Neal Norwitzbb89e682008-03-25 07:00:39 +0000404 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000405
406 def tearDown(self):
Neal Norwitzbb89e682008-03-25 07:00:39 +0000407 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000408 if self.itimer is not None: # test_itimer_exc doesn't change this attr
409 # just ensure that itimer is stopped
410 signal.setitimer(self.itimer, 0)
411
412 def sig_alrm(self, *args):
413 self.hndl_called = True
414 if test_support.verbose:
415 print("SIGALRM handler invoked", args)
416
417 def sig_vtalrm(self, *args):
418 self.hndl_called = True
419
420 if self.hndl_count > 3:
421 # it shouldn't be here, because it should have been disabled.
422 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
423 "timer.")
424 elif self.hndl_count == 3:
425 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
426 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
427 if test_support.verbose:
428 print("last SIGVTALRM handler call")
429
430 self.hndl_count += 1
431
432 if test_support.verbose:
433 print("SIGVTALRM handler invoked", args)
434
435 def sig_prof(self, *args):
436 self.hndl_called = True
437 signal.setitimer(signal.ITIMER_PROF, 0)
438
439 if test_support.verbose:
440 print("SIGPROF handler invoked", args)
441
442 def test_itimer_exc(self):
443 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
444 # defines it ?
445 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Neal Norwitzbb89e682008-03-25 07:00:39 +0000446 # Negative times are treated as zero on some platforms.
447 if 0:
448 self.assertRaises(signal.ItimerError,
449 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000450
451 def test_itimer_real(self):
452 self.itimer = signal.ITIMER_REAL
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000453 signal.setitimer(self.itimer, 1.0)
454 if test_support.verbose:
455 print("\ncall pause()...")
456 signal.pause()
457
458 self.assertEqual(self.hndl_called, True)
459
Stefan Krah68b4e012010-04-20 07:59:10 +0000460 # Issue 3864. Unknown if this affects earlier versions of freebsd also.
Gregory P. Smith886a1cd2010-10-17 04:28:14 +0000461 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
462 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwisaef18b12008-03-24 13:31:16 +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 Dickinson4b841d92009-10-31 10:36:06 +0000468 start_time = time.time()
Stefan Krah68b4e012010-04-20 07:59:10 +0000469 while time.time() - start_time < 60.0:
Mark Dickinson245d9152009-10-04 18:38:39 +0000470 # use up some virtual time by doing real work
471 _ = pow(12345, 67890, 10000019)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000472 if signal.getitimer(self.itimer) == (0.0, 0.0):
473 break # sig_vtalrm handler stopped this itimer
Stefan Krah68b4e012010-04-20 07:59:10 +0000474 else: # Issue 8424
Benjamin Peterson5b5134b2010-05-15 17:48:55 +0000475 self.skipTest("timeout: likely cause: machine too slow or load too "
476 "high")
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000477
478 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti2623a372010-11-21 13:34:58 +0000479 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000480 # and the handler should have been called
Ezio Melotti2623a372010-11-21 13:34:58 +0000481 self.assertEqual(self.hndl_called, True)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000482
Stefan Krah68b4e012010-04-20 07:59:10 +0000483 # Issue 3864. Unknown if this affects earlier versions of freebsd also.
R. David Murraye0e8a872010-04-17 05:26:26 +0000484 @unittest.skipIf(sys.platform=='freebsd6',
485 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000486 def test_itimer_prof(self):
487 self.itimer = signal.ITIMER_PROF
488 signal.signal(signal.SIGPROF, self.sig_prof)
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +0000489 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000490
Mark Dickinson4b841d92009-10-31 10:36:06 +0000491 start_time = time.time()
Stefan Krah68b4e012010-04-20 07:59:10 +0000492 while time.time() - start_time < 60.0:
Mark Dickinson4b841d92009-10-31 10:36:06 +0000493 # do some work
494 _ = pow(12345, 67890, 10000019)
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000495 if signal.getitimer(self.itimer) == (0.0, 0.0):
496 break # sig_prof handler stopped this itimer
Stefan Krah68b4e012010-04-20 07:59:10 +0000497 else: # Issue 8424
Benjamin Peterson5b5134b2010-05-15 17:48:55 +0000498 self.skipTest("timeout: likely cause: machine too slow or load too "
499 "high")
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000500
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +0000501 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti2623a372010-11-21 13:34:58 +0000502 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Jeffrey Yasskin2b860db2008-04-04 04:51:19 +0000503 # and the handler should have been called
Martin v. Löwisaef18b12008-03-24 13:31:16 +0000504 self.assertEqual(self.hndl_called, True)
505
Antoine Pitroua45a99b2017-06-30 10:54:54 +0200506 def test_setitimer_tiny(self):
507 # bpo-30807: C setitimer() takes a microsecond-resolution interval.
508 # Check that float -> timeval conversion doesn't round
509 # the interval down to zero, which would disable the timer.
510 self.itimer = signal.ITIMER_REAL
511 signal.setitimer(self.itimer, 1e-6)
512 time.sleep(1)
513 self.assertEqual(self.hndl_called, True)
514
515
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000516def test_main():
Brian Curtin9d310d32010-08-07 03:56:16 +0000517 test_support.run_unittest(BasicSignalTests, InterProcessSignalTests,
Benjamin Peterson08e153a2013-01-18 00:10:24 -0500518 WakeupFDTests, WakeupSignalTests,
519 SiginterruptTest, ItimerTest,
520 WindowsSignalTests)
Georg Brandl9f2b93e2007-08-24 18:07:52 +0000521
522
523if __name__ == "__main__":
524 test_main()