blob: c1054ed834bf317361d7fe7ed17f3c5506b16e6f [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
Christian Heimes4fbc72b2008-03-22 00:47:35 +00008import subprocess
9import traceback
Christian Heimesc06950e2008-02-28 21:17:00 +000010import sys, os, time, errno
Victor Stinnerb3e72192011-05-08 01:46:11 +020011try:
12 import threading
13except ImportError:
14 threading = None
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")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200194class PosixTests(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
283 def setUp(self):
284 """Install a no-op signal handler that can be set to allow
285 interrupts or not, and arrange for the original signal handler to be
286 re-installed when the test is finished.
287 """
Brian Curtin3f004b12010-08-06 19:34:52 +0000288 self.signum = signal.SIGUSR1
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000289 oldhandler = signal.signal(self.signum, lambda x,y: None)
290 self.addCleanup(signal.signal, self.signum, oldhandler)
291
292 def readpipe_interrupted(self):
293 """Perform a read during which a signal will arrive. Return True if the
294 read is interrupted by the signal and raises an exception. Return False
295 if it returns normally.
296 """
297 # Create a pipe that can be used for the read. Also clean it up
298 # when the test is over, since nothing else will (but see below for
299 # the write end).
Christian Heimes8640e742008-02-23 16:23:06 +0000300 r, w = os.pipe()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000301 self.addCleanup(os.close, r)
302
303 # Create another process which can send a signal to this one to try
304 # to interrupt the read.
Christian Heimes8640e742008-02-23 16:23:06 +0000305 ppid = os.getpid()
306 pid = os.fork()
307
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000308 if pid == 0:
309 # Child code: sleep to give the parent enough time to enter the
310 # read() call (there's a race here, but it's really tricky to
311 # eliminate it); then signal the parent process. Also, sleep
312 # again to make it likely that the signal is delivered to the
313 # parent process before the child exits. If the child exits
314 # first, the write end of the pipe will be closed and the test
315 # is invalid.
Christian Heimes8640e742008-02-23 16:23:06 +0000316 try:
317 time.sleep(0.2)
318 os.kill(ppid, self.signum)
319 time.sleep(0.2)
320 finally:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000321 # No matter what, just exit as fast as possible now.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000322 exit_subprocess()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000323 else:
324 # Parent code.
325 # Make sure the child is eventually reaped, else it'll be a
326 # zombie for the rest of the test suite run.
327 self.addCleanup(os.waitpid, pid, 0)
Christian Heimes8640e742008-02-23 16:23:06 +0000328
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000329 # Close the write end of the pipe. The child has a copy, so
330 # it's not really closed until the child exits. We need it to
331 # close when the child exits so that in the non-interrupt case
332 # the read eventually completes, otherwise we could just close
333 # it *after* the test.
Christian Heimes8640e742008-02-23 16:23:06 +0000334 os.close(w)
335
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000336 # Try the read and report whether it is interrupted or not to
337 # the caller.
Christian Heimes8640e742008-02-23 16:23:06 +0000338 try:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000339 d = os.read(r, 1)
Christian Heimes8640e742008-02-23 16:23:06 +0000340 return False
341 except OSError as err:
342 if err.errno != errno.EINTR:
343 raise
344 return True
Christian Heimes8640e742008-02-23 16:23:06 +0000345
346 def test_without_siginterrupt(self):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000347 """If a signal handler is installed and siginterrupt is not called
348 at all, when that signal arrives, it interrupts a syscall that's in
349 progress.
350 """
351 i = self.readpipe_interrupted()
352 self.assertTrue(i)
353 # Arrival of the signal shouldn't have changed anything.
354 i = self.readpipe_interrupted()
355 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000356
357 def test_siginterrupt_on(self):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000358 """If a signal handler is installed and siginterrupt is called with
359 a true value for the second argument, when that signal arrives, it
360 interrupts a syscall that's in progress.
361 """
362 signal.siginterrupt(self.signum, 1)
363 i = self.readpipe_interrupted()
364 self.assertTrue(i)
365 # Arrival of the signal shouldn't have changed anything.
366 i = self.readpipe_interrupted()
367 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000368
369 def test_siginterrupt_off(self):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000370 """If a signal handler is installed and siginterrupt is called with
371 a false value for the second argument, when that signal arrives, it
372 does not interrupt a syscall that's in progress.
373 """
374 signal.siginterrupt(self.signum, 0)
375 i = self.readpipe_interrupted()
376 self.assertFalse(i)
377 # Arrival of the signal shouldn't have changed anything.
378 i = self.readpipe_interrupted()
379 self.assertFalse(i)
380
381
Brian Curtin3f004b12010-08-06 19:34:52 +0000382@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000383class ItimerTest(unittest.TestCase):
384 def setUp(self):
385 self.hndl_called = False
386 self.hndl_count = 0
387 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000388 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000389
390 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000391 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000392 if self.itimer is not None: # test_itimer_exc doesn't change this attr
393 # just ensure that itimer is stopped
394 signal.setitimer(self.itimer, 0)
395
396 def sig_alrm(self, *args):
397 self.hndl_called = True
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000398 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000399 print("SIGALRM handler invoked", args)
400
401 def sig_vtalrm(self, *args):
402 self.hndl_called = True
403
404 if self.hndl_count > 3:
405 # it shouldn't be here, because it should have been disabled.
406 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
407 "timer.")
408 elif self.hndl_count == 3:
409 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
410 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000411 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000412 print("last SIGVTALRM handler call")
413
414 self.hndl_count += 1
415
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000416 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000417 print("SIGVTALRM handler invoked", args)
418
419 def sig_prof(self, *args):
420 self.hndl_called = True
421 signal.setitimer(signal.ITIMER_PROF, 0)
422
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000423 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000424 print("SIGPROF handler invoked", args)
425
426 def test_itimer_exc(self):
427 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
428 # defines it ?
429 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000430 # Negative times are treated as zero on some platforms.
431 if 0:
432 self.assertRaises(signal.ItimerError,
433 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000434
435 def test_itimer_real(self):
436 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000437 signal.setitimer(self.itimer, 1.0)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000438 if support.verbose:
Martin v. Löwis823725e2008-03-24 13:39:54 +0000439 print("\ncall pause()...")
440 signal.pause()
441
442 self.assertEqual(self.hndl_called, True)
443
R. David Murray44546f82010-04-21 01:59:28 +0000444 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000445 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
446 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000447 def test_itimer_virtual(self):
448 self.itimer = signal.ITIMER_VIRTUAL
449 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
450 signal.setitimer(self.itimer, 0.3, 0.2)
451
Mark Dickinson78373472009-10-31 10:39:21 +0000452 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000453 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000454 # use up some virtual time by doing real work
455 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000456 if signal.getitimer(self.itimer) == (0.0, 0.0):
457 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000458 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000459 self.skipTest("timeout: likely cause: machine too slow or load too "
460 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000461
462 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000463 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000464 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000465 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000466
R. David Murray44546f82010-04-21 01:59:28 +0000467 # Issue 3864, unknown if this affects earlier versions of freebsd also
468 @unittest.skipIf(sys.platform=='freebsd6',
469 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000470 def test_itimer_prof(self):
471 self.itimer = signal.ITIMER_PROF
472 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000473 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000474
Mark Dickinson78373472009-10-31 10:39:21 +0000475 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000476 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000477 # do some work
478 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000479 if signal.getitimer(self.itimer) == (0.0, 0.0):
480 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000481 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000482 self.skipTest("timeout: likely cause: machine too slow or load too "
483 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000484
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000485 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000486 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000487 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000488 self.assertEqual(self.hndl_called, True)
489
Victor Stinnera9293352011-04-30 15:21:58 +0200490
Victor Stinner35b300c2011-05-04 13:20:35 +0200491class PendingSignalsTests(unittest.TestCase):
492 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200493 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
494 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200495 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200496 def setUp(self):
497 self.has_pthread_kill = hasattr(signal, 'pthread_kill')
498
Victor Stinner35b300c2011-05-04 13:20:35 +0200499 def handler(self, signum, frame):
500 1/0
501
502 def read_sigmask(self):
503 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
504
Victor Stinnerb3e72192011-05-08 01:46:11 +0200505 def can_test_blocked_signals(self, skip):
506 """
507 Check if a blocked signal can be raised to the main thread without
508 calling its signal handler. We need pthread_kill() or exactly one
509 thread (the main thread).
Victor Stinnera9293352011-04-30 15:21:58 +0200510
Victor Stinnerb3e72192011-05-08 01:46:11 +0200511 Return True if it's possible. Otherwise, return False and print a
512 warning if skip is False, or raise a SkipTest exception if skip is
513 True.
514 """
515 if self.has_pthread_kill:
516 return True
Victor Stinnera9293352011-04-30 15:21:58 +0200517
Victor Stinnerf44ce872011-05-03 17:20:31 +0200518 # The fault handler timeout thread masks all signals. If the main
519 # thread masks also SIGUSR1, all threads mask this signal. In this
520 # case, if we send SIGUSR1 to the process, the signal is pending in the
521 # main or the faulthandler timeout thread. Unblock SIGUSR1 in the main
522 # thread calls the signal handler only if the signal is pending for the
Victor Stinnerb3e72192011-05-08 01:46:11 +0200523 # main thread. Stop the faulthandler timeout thread to workaround this
524 # problem.
525 import faulthandler
Victor Stinnerf44ce872011-05-03 17:20:31 +0200526 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner2d4a91e2011-05-03 14:11:22 +0200527
Victor Stinnerb3e72192011-05-08 01:46:11 +0200528 # Issue #11998: The _tkinter module loads the Tcl library which
529 # creates a thread waiting events in select(). This thread receives
530 # signals blocked by all other threads. We cannot test blocked
531 # signals
532 if '_tkinter' in sys.modules:
533 message = ("_tkinter is loaded and pthread_kill() is missing, "
534 "cannot test blocked signals (issue #11998)")
535 if skip:
536 self.skipTest(message)
537 else:
538 print("WARNING: %s" % message)
539 return False
540 return True
541
542 def kill(self, signum):
543 if self.has_pthread_kill:
544 tid = threading.current_thread().ident
545 signal.pthread_kill(tid, signum)
546 else:
547 pid = os.getpid()
548 os.kill(pid, signum)
549
550 @unittest.skipUnless(hasattr(signal, 'sigpending'),
551 'need signal.sigpending()')
552 def test_sigpending_empty(self):
553 self.assertEqual(signal.sigpending(), set())
554
555 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
556 'need signal.pthread_sigmask()')
557 @unittest.skipUnless(hasattr(signal, 'sigpending'),
558 'need signal.sigpending()')
559 def test_sigpending(self):
560 self.can_test_blocked_signals(True)
561
562 signum = signal.SIGUSR1
563 old_handler = signal.signal(signum, self.handler)
564 self.addCleanup(signal.signal, signum, old_handler)
565
566 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
567 self.kill(signum)
568 self.assertEqual(signal.sigpending(), {signum})
569 with self.assertRaises(ZeroDivisionError):
570 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
571
572 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
573 'need signal.pthread_kill()')
574 def test_pthread_kill(self):
575 signum = signal.SIGUSR1
576 current = threading.current_thread().ident
577
578 old_handler = signal.signal(signum, self.handler)
579 self.addCleanup(signal.signal, signum, old_handler)
580
581 with self.assertRaises(ZeroDivisionError):
582 signal.pthread_kill(current, signum)
583
584 @unittest.skipUnless(hasattr(signal, 'sigwait'),
585 'need signal.sigwait()')
586 def test_sigwait(self):
587 old_handler = signal.signal(signal.SIGALRM, self.handler)
588 self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
589
590 signal.alarm(1)
591 self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)
592
593 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
594 'need signal.pthread_sigmask()')
595 def test_pthread_sigmask_arguments(self):
596 self.assertRaises(TypeError, signal.pthread_sigmask)
597 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
598 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
599 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
600
601 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
602 'need signal.pthread_sigmask()')
603 def test_pthread_sigmask(self):
604 test_blocked_signals = self.can_test_blocked_signals(False)
605 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200606
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200607 # Install our signal handler
Victor Stinner35b300c2011-05-04 13:20:35 +0200608 old_handler = signal.signal(signum, self.handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200609 self.addCleanup(signal.signal, signum, old_handler)
610
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200611 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200612 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
613 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200614 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200615 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200616
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200617 # Block and then raise SIGUSR1. The signal is blocked: the signal
618 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200619 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerb3e72192011-05-08 01:46:11 +0200620 if test_blocked_signals:
621 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200622
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200623 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200624 blocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200625 self.assertIn(signum, blocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200626 self.assertEqual(old_mask ^ blocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200627
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200628 # Unblock SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200629 if test_blocked_signals:
Victor Stinner6fd49e12011-05-04 12:38:03 +0200630 with self.assertRaises(ZeroDivisionError):
631 # unblock the pending signal calls immediatly the signal handler
632 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
633 else:
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200634 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
635 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200636 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 unblocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200640 self.assertNotIn(signum, unblocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200641 self.assertEqual(blocked ^ unblocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200642 self.assertSequenceEqual(old_mask, unblocked)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200643 # Finally, restore the previous signal handler and the signal mask
Victor Stinnera9293352011-04-30 15:21:58 +0200644
645
Thomas Woutersed03b412007-08-28 21:37:11 +0000646def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100647 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200648 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100649 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200650 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200651 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100652 finally:
653 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000654
655
656if __name__ == "__main__":
657 test_main()