blob: 80b9744dea09ce7812e35dea8fa2f50002bd93d0 [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
Benjamin Petersonee8712c2008-05-20 21:35:26 +000061 if support.verbose:
Christian Heimes5e696852008-04-09 08:37:03 +000062 print("handlerA invoked from signal %s at:\n%s" % (
63 signum, self.format_frame(frame, limit=1)))
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000064
Christian Heimes5e696852008-04-09 08:37:03 +000065 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000066 self.b_called = True
Benjamin Petersonee8712c2008-05-20 21:35:26 +000067 if support.verbose:
Christian Heimes5e696852008-04-09 08:37:03 +000068 print ("handlerB invoked from signal %s at:\n%s" % (
69 signum, self.format_frame(frame, limit=1)))
70 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000071
Christian Heimes4fbc72b2008-03-22 00:47:35 +000072 def wait(self, child):
73 """Wait for child to finish, ignoring EINTR."""
74 while True:
75 try:
76 child.wait()
77 return
78 except OSError as e:
79 if e.errno != errno.EINTR:
80 raise
Fred Drake004d5e62000-10-23 17:22:08 +000081
Christian Heimes4fbc72b2008-03-22 00:47:35 +000082 def run_test(self):
83 # Install handlers. This function runs in a sub-process, so we
84 # don't worry about re-setting the default handlers.
85 signal.signal(signal.SIGHUP, self.handlerA)
86 signal.signal(signal.SIGUSR1, self.handlerB)
87 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
88 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000089
Christian Heimes4fbc72b2008-03-22 00:47:35 +000090 # Variables the signals will modify:
91 self.a_called = False
92 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000093
Christian Heimes4fbc72b2008-03-22 00:47:35 +000094 # Let the sub-processes know who to send signals to.
95 pid = os.getpid()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000096 if support.verbose:
Thomas Woutersed03b412007-08-28 21:37:11 +000097 print("test runner's pid is", pid)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000098
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000099 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
100 if child:
101 self.wait(child)
102 if not self.a_called:
103 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000104 self.assertTrue(self.a_called)
105 self.assertFalse(self.b_called)
106 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000107
Christian Heimes5e696852008-04-09 08:37:03 +0000108 # Make sure the signal isn't delivered while the previous
109 # Popen object is being destroyed, because __del__ swallows
110 # exceptions.
111 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000112 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000113 child = subprocess.Popen(['kill', '-USR1', str(pid)])
114 # This wait should be interrupted by the signal's exception.
115 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000116 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000117 self.fail('HandlerBCalled exception not thrown')
118 except HandlerBCalled:
119 self.assertTrue(self.b_called)
120 self.assertFalse(self.a_called)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000121 if support.verbose:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000122 print("HandlerBCalled exception caught")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000123
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000124 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
125 if child:
126 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000127
128 try:
129 signal.alarm(1)
130 # The race condition in pause doesn't matter in this case,
131 # since alarm is going to raise a KeyboardException, which
132 # will skip the call.
133 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000134 # But if another signal arrives before the alarm, pause
135 # may return early.
136 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000137 except KeyboardInterrupt:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000138 if support.verbose:
Thomas Woutersed03b412007-08-28 21:37:11 +0000139 print("KeyboardInterrupt (the alarm() went off)")
Thomas Woutersed03b412007-08-28 21:37:11 +0000140 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000141 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000142 traceback.format_exc())
143 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000144 self.fail("pause returned of its own accord, and the signal"
145 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000146
R. David Murray44546f82010-04-21 01:59:28 +0000147 # Issue 3864, unknown if this affects earlier versions of freebsd also
148 @unittest.skipIf(sys.platform=='freebsd6',
149 'inter process signals not reliable (do not mix well with threading) '
150 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000151 def test_main(self):
152 # This function spawns a child process to insulate the main
153 # test-running process from all the signals. It then
154 # communicates with that child process over a pipe and
155 # re-raises information about any exceptions the child
156 # throws. The real work happens in self.run_test().
157 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000158 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
159 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000160 child = os.fork()
161 if child == 0:
162 # In the child process; run the test and report results
163 # through the pipe.
164 try:
165 done_r.close()
166 # Have to close done_w again here because
167 # exit_subprocess() will skip the enclosing with block.
168 with closing(done_w):
169 try:
170 self.run_test()
171 except:
172 pickle.dump(traceback.format_exc(), done_w)
173 else:
174 pickle.dump(None, done_w)
175 except:
176 print('Uh oh, raised from pickle.')
177 traceback.print_exc()
178 finally:
179 exit_subprocess()
180
181 done_w.close()
182 # Block for up to MAX_DURATION seconds for the test to finish.
183 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
184 if done_r in r:
185 tb = pickle.load(done_r)
186 if tb:
187 self.fail(tb)
188 else:
189 os.kill(child, signal.SIGKILL)
190 self.fail('Test deadlocked after %d seconds.' %
191 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000192
193
Brian Curtin3f004b12010-08-06 19:34:52 +0000194@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200195class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000196 def trivial_signal_handler(self, *args):
197 pass
198
Thomas Woutersed03b412007-08-28 21:37:11 +0000199 def test_out_of_range_signal_number_raises_error(self):
200 self.assertRaises(ValueError, signal.getsignal, 4242)
201
Thomas Woutersed03b412007-08-28 21:37:11 +0000202 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000203 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000204
205 def test_setting_signal_handler_to_none_raises_error(self):
206 self.assertRaises(TypeError, signal.signal,
207 signal.SIGUSR1, None)
208
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000209 def test_getsignal(self):
210 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000211 self.assertEqual(signal.getsignal(signal.SIGHUP),
212 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000213 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000214 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000215
216
Brian Curtin3f004b12010-08-06 19:34:52 +0000217@unittest.skipUnless(sys.platform == "win32", "Windows specific")
218class WindowsSignalTests(unittest.TestCase):
219 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000220 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000221 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +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 Curtin3f004b12010-08-06 19:34:52 +0000227
228 with self.assertRaises(ValueError):
229 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000230
231 with self.assertRaises(ValueError):
232 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000233
234
235@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000236class WakeupSignalTests(unittest.TestCase):
237 TIMEOUT_FULL = 10
238 TIMEOUT_HALF = 5
239
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200240 def check_signum(self, *signals):
241 data = os.read(self.read, len(signals)+1)
242 raised = struct.unpack('%uB' % len(data), data)
243 self.assertSequenceEqual(raised, signals)
244
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000245 def test_wakeup_fd_early(self):
246 import select
247
248 signal.alarm(1)
249 before_time = time.time()
250 # We attempt to get a signal during the sleep,
251 # before select is called
252 time.sleep(self.TIMEOUT_FULL)
253 mid_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000254 self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000255 select.select([self.read], [], [], self.TIMEOUT_FULL)
256 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000257 self.assertTrue(after_time - mid_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200258 self.check_signum(signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000259
260 def test_wakeup_fd_during(self):
261 import select
262
263 signal.alarm(1)
264 before_time = time.time()
265 # We attempt to get a signal during the select call
266 self.assertRaises(select.error, select.select,
267 [self.read], [], [], self.TIMEOUT_FULL)
268 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000269 self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200270 self.check_signum(signal.SIGALRM)
271
272 def test_signum(self):
273 old_handler = signal.signal(signal.SIGUSR1, lambda x,y:None)
274 self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)
275 os.kill(os.getpid(), signal.SIGUSR1)
276 os.kill(os.getpid(), signal.SIGALRM)
277 self.check_signum(signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000278
279 def setUp(self):
280 import fcntl
281
282 self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
283 self.read, self.write = os.pipe()
284 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
285 flags = flags | os.O_NONBLOCK
286 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
287 self.old_wakeup = signal.set_wakeup_fd(self.write)
288
289 def tearDown(self):
290 signal.set_wakeup_fd(self.old_wakeup)
291 os.close(self.read)
292 os.close(self.write)
293 signal.signal(signal.SIGALRM, self.alrm)
294
Brian Curtin3f004b12010-08-06 19:34:52 +0000295@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000296class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000297
298 def setUp(self):
299 """Install a no-op signal handler that can be set to allow
300 interrupts or not, and arrange for the original signal handler to be
301 re-installed when the test is finished.
302 """
Brian Curtin3f004b12010-08-06 19:34:52 +0000303 self.signum = signal.SIGUSR1
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000304 oldhandler = signal.signal(self.signum, lambda x,y: None)
305 self.addCleanup(signal.signal, self.signum, oldhandler)
306
307 def readpipe_interrupted(self):
308 """Perform a read during which a signal will arrive. Return True if the
309 read is interrupted by the signal and raises an exception. Return False
310 if it returns normally.
311 """
312 # Create a pipe that can be used for the read. Also clean it up
313 # when the test is over, since nothing else will (but see below for
314 # the write end).
Christian Heimes8640e742008-02-23 16:23:06 +0000315 r, w = os.pipe()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000316 self.addCleanup(os.close, r)
317
318 # Create another process which can send a signal to this one to try
319 # to interrupt the read.
Christian Heimes8640e742008-02-23 16:23:06 +0000320 ppid = os.getpid()
321 pid = os.fork()
322
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000323 if pid == 0:
324 # Child code: sleep to give the parent enough time to enter the
325 # read() call (there's a race here, but it's really tricky to
326 # eliminate it); then signal the parent process. Also, sleep
327 # again to make it likely that the signal is delivered to the
328 # parent process before the child exits. If the child exits
329 # first, the write end of the pipe will be closed and the test
330 # is invalid.
Christian Heimes8640e742008-02-23 16:23:06 +0000331 try:
332 time.sleep(0.2)
333 os.kill(ppid, self.signum)
334 time.sleep(0.2)
335 finally:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000336 # No matter what, just exit as fast as possible now.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000337 exit_subprocess()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000338 else:
339 # Parent code.
340 # Make sure the child is eventually reaped, else it'll be a
341 # zombie for the rest of the test suite run.
342 self.addCleanup(os.waitpid, pid, 0)
Christian Heimes8640e742008-02-23 16:23:06 +0000343
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000344 # Close the write end of the pipe. The child has a copy, so
345 # it's not really closed until the child exits. We need it to
346 # close when the child exits so that in the non-interrupt case
347 # the read eventually completes, otherwise we could just close
348 # it *after* the test.
Christian Heimes8640e742008-02-23 16:23:06 +0000349 os.close(w)
350
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000351 # Try the read and report whether it is interrupted or not to
352 # the caller.
Christian Heimes8640e742008-02-23 16:23:06 +0000353 try:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000354 d = os.read(r, 1)
Christian Heimes8640e742008-02-23 16:23:06 +0000355 return False
356 except OSError as err:
357 if err.errno != errno.EINTR:
358 raise
359 return True
Christian Heimes8640e742008-02-23 16:23:06 +0000360
361 def test_without_siginterrupt(self):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000362 """If a signal handler is installed and siginterrupt is not called
363 at all, when that signal arrives, it interrupts a syscall that's in
364 progress.
365 """
366 i = self.readpipe_interrupted()
367 self.assertTrue(i)
368 # Arrival of the signal shouldn't have changed anything.
369 i = self.readpipe_interrupted()
370 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000371
372 def test_siginterrupt_on(self):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000373 """If a signal handler is installed and siginterrupt is called with
374 a true value for the second argument, when that signal arrives, it
375 interrupts a syscall that's in progress.
376 """
377 signal.siginterrupt(self.signum, 1)
378 i = self.readpipe_interrupted()
379 self.assertTrue(i)
380 # Arrival of the signal shouldn't have changed anything.
381 i = self.readpipe_interrupted()
382 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000383
384 def test_siginterrupt_off(self):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000385 """If a signal handler is installed and siginterrupt is called with
386 a false value for the second argument, when that signal arrives, it
387 does not interrupt a syscall that's in progress.
388 """
389 signal.siginterrupt(self.signum, 0)
390 i = self.readpipe_interrupted()
391 self.assertFalse(i)
392 # Arrival of the signal shouldn't have changed anything.
393 i = self.readpipe_interrupted()
394 self.assertFalse(i)
395
396
Brian Curtin3f004b12010-08-06 19:34:52 +0000397@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000398class ItimerTest(unittest.TestCase):
399 def setUp(self):
400 self.hndl_called = False
401 self.hndl_count = 0
402 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000403 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000404
405 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000406 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000407 if self.itimer is not None: # test_itimer_exc doesn't change this attr
408 # just ensure that itimer is stopped
409 signal.setitimer(self.itimer, 0)
410
411 def sig_alrm(self, *args):
412 self.hndl_called = True
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000413 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000414 print("SIGALRM handler invoked", args)
415
416 def sig_vtalrm(self, *args):
417 self.hndl_called = True
418
419 if self.hndl_count > 3:
420 # it shouldn't be here, because it should have been disabled.
421 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
422 "timer.")
423 elif self.hndl_count == 3:
424 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
425 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000426 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000427 print("last SIGVTALRM handler call")
428
429 self.hndl_count += 1
430
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000431 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000432 print("SIGVTALRM handler invoked", args)
433
434 def sig_prof(self, *args):
435 self.hndl_called = True
436 signal.setitimer(signal.ITIMER_PROF, 0)
437
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000438 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000439 print("SIGPROF handler invoked", args)
440
441 def test_itimer_exc(self):
442 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
443 # defines it ?
444 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000445 # Negative times are treated as zero on some platforms.
446 if 0:
447 self.assertRaises(signal.ItimerError,
448 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000449
450 def test_itimer_real(self):
451 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000452 signal.setitimer(self.itimer, 1.0)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000453 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000454 print("\ncall pause()...")
455 signal.pause()
456
457 self.assertEqual(self.hndl_called, True)
458
R. David Murray44546f82010-04-21 01:59:28 +0000459 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000460 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
461 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000462 def test_itimer_virtual(self):
463 self.itimer = signal.ITIMER_VIRTUAL
464 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
465 signal.setitimer(self.itimer, 0.3, 0.2)
466
Mark Dickinson78373472009-10-31 10:39:21 +0000467 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000468 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000469 # use up some virtual time by doing real work
470 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000471 if signal.getitimer(self.itimer) == (0.0, 0.0):
472 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000473 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000474 self.skipTest("timeout: likely cause: machine too slow or load too "
475 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000476
477 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000478 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000479 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000480 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000481
R. David Murray44546f82010-04-21 01:59:28 +0000482 # Issue 3864, unknown if this affects earlier versions of freebsd also
483 @unittest.skipIf(sys.platform=='freebsd6',
484 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000485 def test_itimer_prof(self):
486 self.itimer = signal.ITIMER_PROF
487 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000488 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000489
Mark Dickinson78373472009-10-31 10:39:21 +0000490 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000491 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000492 # do some work
493 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000494 if signal.getitimer(self.itimer) == (0.0, 0.0):
495 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000496 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000497 self.skipTest("timeout: likely cause: machine too slow or load too "
498 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000499
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000500 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000501 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000502 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000503 self.assertEqual(self.hndl_called, True)
504
Victor Stinnera9293352011-04-30 15:21:58 +0200505
Victor Stinner35b300c2011-05-04 13:20:35 +0200506class PendingSignalsTests(unittest.TestCase):
507 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200508 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
509 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200510 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200511 def setUp(self):
512 self.has_pthread_kill = hasattr(signal, 'pthread_kill')
513
Victor Stinner35b300c2011-05-04 13:20:35 +0200514 def handler(self, signum, frame):
515 1/0
516
517 def read_sigmask(self):
518 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
519
Victor Stinnerb3e72192011-05-08 01:46:11 +0200520 def can_test_blocked_signals(self, skip):
521 """
522 Check if a blocked signal can be raised to the main thread without
523 calling its signal handler. We need pthread_kill() or exactly one
524 thread (the main thread).
Victor Stinnera9293352011-04-30 15:21:58 +0200525
Victor Stinnerb3e72192011-05-08 01:46:11 +0200526 Return True if it's possible. Otherwise, return False and print a
527 warning if skip is False, or raise a SkipTest exception if skip is
528 True.
529 """
530 if self.has_pthread_kill:
531 return True
Victor Stinnera9293352011-04-30 15:21:58 +0200532
Victor Stinnerf44ce872011-05-03 17:20:31 +0200533 # The fault handler timeout thread masks all signals. If the main
534 # thread masks also SIGUSR1, all threads mask this signal. In this
535 # case, if we send SIGUSR1 to the process, the signal is pending in the
536 # main or the faulthandler timeout thread. Unblock SIGUSR1 in the main
537 # thread calls the signal handler only if the signal is pending for the
Victor Stinnerb3e72192011-05-08 01:46:11 +0200538 # main thread. Stop the faulthandler timeout thread to workaround this
539 # problem.
540 import faulthandler
Victor Stinnerf44ce872011-05-03 17:20:31 +0200541 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner2d4a91e2011-05-03 14:11:22 +0200542
Victor Stinnerb3e72192011-05-08 01:46:11 +0200543 # Issue #11998: The _tkinter module loads the Tcl library which
544 # creates a thread waiting events in select(). This thread receives
545 # signals blocked by all other threads. We cannot test blocked
546 # signals
547 if '_tkinter' in sys.modules:
548 message = ("_tkinter is loaded and pthread_kill() is missing, "
549 "cannot test blocked signals (issue #11998)")
550 if skip:
551 self.skipTest(message)
552 else:
553 print("WARNING: %s" % message)
554 return False
555 return True
556
557 def kill(self, signum):
558 if self.has_pthread_kill:
559 tid = threading.current_thread().ident
560 signal.pthread_kill(tid, signum)
561 else:
562 pid = os.getpid()
563 os.kill(pid, signum)
564
565 @unittest.skipUnless(hasattr(signal, 'sigpending'),
566 'need signal.sigpending()')
567 def test_sigpending_empty(self):
568 self.assertEqual(signal.sigpending(), set())
569
570 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
571 'need signal.pthread_sigmask()')
572 @unittest.skipUnless(hasattr(signal, 'sigpending'),
573 'need signal.sigpending()')
574 def test_sigpending(self):
575 self.can_test_blocked_signals(True)
576
577 signum = signal.SIGUSR1
578 old_handler = signal.signal(signum, self.handler)
579 self.addCleanup(signal.signal, signum, old_handler)
580
581 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
582 self.kill(signum)
583 self.assertEqual(signal.sigpending(), {signum})
584 with self.assertRaises(ZeroDivisionError):
585 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
586
587 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
588 'need signal.pthread_kill()')
589 def test_pthread_kill(self):
590 signum = signal.SIGUSR1
591 current = threading.current_thread().ident
592
593 old_handler = signal.signal(signum, self.handler)
594 self.addCleanup(signal.signal, signum, old_handler)
595
596 with self.assertRaises(ZeroDivisionError):
597 signal.pthread_kill(current, signum)
598
599 @unittest.skipUnless(hasattr(signal, 'sigwait'),
600 'need signal.sigwait()')
601 def test_sigwait(self):
602 old_handler = signal.signal(signal.SIGALRM, self.handler)
603 self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
604
605 signal.alarm(1)
606 self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)
607
608 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
609 'need signal.pthread_sigmask()')
610 def test_pthread_sigmask_arguments(self):
611 self.assertRaises(TypeError, signal.pthread_sigmask)
612 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
613 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
614 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
615
616 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
617 'need signal.pthread_sigmask()')
618 def test_pthread_sigmask(self):
619 test_blocked_signals = self.can_test_blocked_signals(False)
620 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200621
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200622 # Install our signal handler
Victor Stinner35b300c2011-05-04 13:20:35 +0200623 old_handler = signal.signal(signum, self.handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200624 self.addCleanup(signal.signal, signum, old_handler)
625
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200626 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200627 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
628 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200629 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200630 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200631
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200632 # Block and then raise SIGUSR1. The signal is blocked: the signal
633 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200634 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerb3e72192011-05-08 01:46:11 +0200635 if test_blocked_signals:
636 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200637
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200638 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200639 blocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200640 self.assertIn(signum, blocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200641 self.assertEqual(old_mask ^ blocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200642
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200643 # Unblock SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200644 if test_blocked_signals:
Victor Stinner6fd49e12011-05-04 12:38:03 +0200645 with self.assertRaises(ZeroDivisionError):
646 # unblock the pending signal calls immediatly the signal handler
647 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
648 else:
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200649 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
650 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200651 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200652
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200653 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200654 unblocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200655 self.assertNotIn(signum, unblocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200656 self.assertEqual(blocked ^ unblocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200657 self.assertSequenceEqual(old_mask, unblocked)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200658 # Finally, restore the previous signal handler and the signal mask
Victor Stinnera9293352011-04-30 15:21:58 +0200659
660
Thomas Woutersed03b412007-08-28 21:37:11 +0000661def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100662 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200663 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100664 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200665 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200666 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100667 finally:
668 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000669
670
671if __name__ == "__main__":
672 test_main()