blob: 31340315729412a3806eb9211647f0aef777e037 [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
Guido van Rossum4f17e3e1995-03-16 15:07:38 +000061
Christian Heimes5e696852008-04-09 08:37:03 +000062 def handlerB(self, signum, frame):
Thomas Woutersed03b412007-08-28 21:37:11 +000063 self.b_called = True
Christian Heimes5e696852008-04-09 08:37:03 +000064 raise HandlerBCalled(signum, self.format_frame(frame))
Neal Norwitz9730bcb2006-01-23 07:50:06 +000065
Christian Heimes4fbc72b2008-03-22 00:47:35 +000066 def wait(self, child):
67 """Wait for child to finish, ignoring EINTR."""
68 while True:
69 try:
70 child.wait()
71 return
72 except OSError as e:
73 if e.errno != errno.EINTR:
74 raise
Fred Drake004d5e62000-10-23 17:22:08 +000075
Christian Heimes4fbc72b2008-03-22 00:47:35 +000076 def run_test(self):
77 # Install handlers. This function runs in a sub-process, so we
78 # don't worry about re-setting the default handlers.
79 signal.signal(signal.SIGHUP, self.handlerA)
80 signal.signal(signal.SIGUSR1, self.handlerB)
81 signal.signal(signal.SIGUSR2, signal.SIG_IGN)
82 signal.signal(signal.SIGALRM, signal.default_int_handler)
Michael W. Hudson5c26e862004-06-11 18:09:28 +000083
Christian Heimes4fbc72b2008-03-22 00:47:35 +000084 # Variables the signals will modify:
85 self.a_called = False
86 self.b_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000087
Christian Heimes4fbc72b2008-03-22 00:47:35 +000088 # Let the sub-processes know who to send signals to.
89 pid = os.getpid()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000090
Benjamin Petersonad9d48d2008-04-02 21:49:44 +000091 child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)])
92 if child:
93 self.wait(child)
94 if not self.a_called:
95 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +000096 self.assertTrue(self.a_called)
97 self.assertFalse(self.b_called)
98 self.a_called = False
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000099
Christian Heimes5e696852008-04-09 08:37:03 +0000100 # Make sure the signal isn't delivered while the previous
101 # Popen object is being destroyed, because __del__ swallows
102 # exceptions.
103 del child
Thomas Woutersed03b412007-08-28 21:37:11 +0000104 try:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000105 child = subprocess.Popen(['kill', '-USR1', str(pid)])
106 # This wait should be interrupted by the signal's exception.
107 self.wait(child)
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000108 time.sleep(1) # Give the signal time to be delivered.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000109 self.fail('HandlerBCalled exception not thrown')
110 except HandlerBCalled:
111 self.assertTrue(self.b_called)
112 self.assertFalse(self.a_called)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000113
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000114 child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
115 if child:
116 self.wait(child) # Nothing should happen.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000117
118 try:
119 signal.alarm(1)
120 # The race condition in pause doesn't matter in this case,
121 # since alarm is going to raise a KeyboardException, which
122 # will skip the call.
123 signal.pause()
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000124 # But if another signal arrives before the alarm, pause
125 # may return early.
126 time.sleep(1)
Thomas Woutersed03b412007-08-28 21:37:11 +0000127 except KeyboardInterrupt:
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200128 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000129 except:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000130 self.fail("Some other exception woke us from pause: %s" %
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000131 traceback.format_exc())
132 else:
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000133 self.fail("pause returned of its own accord, and the signal"
134 " didn't arrive after another second.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000135
R. David Murray44546f82010-04-21 01:59:28 +0000136 # Issue 3864, unknown if this affects earlier versions of freebsd also
137 @unittest.skipIf(sys.platform=='freebsd6',
138 'inter process signals not reliable (do not mix well with threading) '
139 'on freebsd6')
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000140 def test_main(self):
141 # This function spawns a child process to insulate the main
142 # test-running process from all the signals. It then
143 # communicates with that child process over a pipe and
144 # re-raises information about any exceptions the child
145 # throws. The real work happens in self.run_test().
146 os_done_r, os_done_w = os.pipe()
Raymond Hettinger686057b2009-06-04 00:11:54 +0000147 with closing(os.fdopen(os_done_r, 'rb')) as done_r, \
148 closing(os.fdopen(os_done_w, 'wb')) as done_w:
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000149 child = os.fork()
150 if child == 0:
151 # In the child process; run the test and report results
152 # through the pipe.
153 try:
154 done_r.close()
155 # Have to close done_w again here because
156 # exit_subprocess() will skip the enclosing with block.
157 with closing(done_w):
158 try:
159 self.run_test()
160 except:
161 pickle.dump(traceback.format_exc(), done_w)
162 else:
163 pickle.dump(None, done_w)
164 except:
165 print('Uh oh, raised from pickle.')
166 traceback.print_exc()
167 finally:
168 exit_subprocess()
169
170 done_w.close()
171 # Block for up to MAX_DURATION seconds for the test to finish.
172 r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
173 if done_r in r:
174 tb = pickle.load(done_r)
175 if tb:
176 self.fail(tb)
177 else:
178 os.kill(child, signal.SIGKILL)
179 self.fail('Test deadlocked after %d seconds.' %
180 self.MAX_DURATION)
Thomas Woutersed03b412007-08-28 21:37:11 +0000181
182
Brian Curtin3f004b12010-08-06 19:34:52 +0000183@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Victor Stinnerb3e72192011-05-08 01:46:11 +0200184class PosixTests(unittest.TestCase):
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000185 def trivial_signal_handler(self, *args):
186 pass
187
Thomas Woutersed03b412007-08-28 21:37:11 +0000188 def test_out_of_range_signal_number_raises_error(self):
189 self.assertRaises(ValueError, signal.getsignal, 4242)
190
Thomas Woutersed03b412007-08-28 21:37:11 +0000191 self.assertRaises(ValueError, signal.signal, 4242,
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000192 self.trivial_signal_handler)
Thomas Woutersed03b412007-08-28 21:37:11 +0000193
194 def test_setting_signal_handler_to_none_raises_error(self):
195 self.assertRaises(TypeError, signal.signal,
196 signal.SIGUSR1, None)
197
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000198 def test_getsignal(self):
199 hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000200 self.assertEqual(signal.getsignal(signal.SIGHUP),
201 self.trivial_signal_handler)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000202 signal.signal(signal.SIGHUP, hup)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000203 self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000204
205
Brian Curtin3f004b12010-08-06 19:34:52 +0000206@unittest.skipUnless(sys.platform == "win32", "Windows specific")
207class WindowsSignalTests(unittest.TestCase):
208 def test_issue9324(self):
Brian Curtineccd4d92010-10-01 15:09:53 +0000209 # Updated for issue #10003, adding SIGBREAK
Brian Curtin3f004b12010-08-06 19:34:52 +0000210 handler = lambda x, y: None
Brian Curtineccd4d92010-10-01 15:09:53 +0000211 for sig in (signal.SIGABRT, signal.SIGBREAK, signal.SIGFPE,
212 signal.SIGILL, signal.SIGINT, signal.SIGSEGV,
213 signal.SIGTERM):
214 # Set and then reset a handler for signals that work on windows
215 signal.signal(sig, signal.signal(sig, handler))
Brian Curtin3f004b12010-08-06 19:34:52 +0000216
217 with self.assertRaises(ValueError):
218 signal.signal(-1, handler)
Brian Curtin80cd4bf2010-08-07 03:52:38 +0000219
220 with self.assertRaises(ValueError):
221 signal.signal(7, handler)
Brian Curtin3f004b12010-08-06 19:34:52 +0000222
223
224@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000225class WakeupSignalTests(unittest.TestCase):
226 TIMEOUT_FULL = 10
227 TIMEOUT_HALF = 5
228
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200229 def check_signum(self, *signals):
230 data = os.read(self.read, len(signals)+1)
231 raised = struct.unpack('%uB' % len(data), data)
232 self.assertSequenceEqual(raised, signals)
233
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000234 def test_wakeup_fd_early(self):
235 import select
236
237 signal.alarm(1)
238 before_time = time.time()
239 # We attempt to get a signal during the sleep,
240 # before select is called
241 time.sleep(self.TIMEOUT_FULL)
242 mid_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000243 self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000244 select.select([self.read], [], [], self.TIMEOUT_FULL)
245 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000246 self.assertTrue(after_time - mid_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200247 self.check_signum(signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000248
249 def test_wakeup_fd_during(self):
250 import select
251
252 signal.alarm(1)
253 before_time = time.time()
254 # We attempt to get a signal during the select call
255 self.assertRaises(select.error, select.select,
256 [self.read], [], [], self.TIMEOUT_FULL)
257 after_time = time.time()
Georg Brandlab91fde2009-08-13 08:51:18 +0000258 self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
Victor Stinnerd49b1f12011-05-08 02:03:15 +0200259 self.check_signum(signal.SIGALRM)
260
261 def test_signum(self):
262 old_handler = signal.signal(signal.SIGUSR1, lambda x,y:None)
263 self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)
264 os.kill(os.getpid(), signal.SIGUSR1)
265 os.kill(os.getpid(), signal.SIGALRM)
266 self.check_signum(signal.SIGUSR1, signal.SIGALRM)
Christian Heimes5fb7c2a2007-12-24 08:52:31 +0000267
268 def setUp(self):
269 import fcntl
270
271 self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
272 self.read, self.write = os.pipe()
273 flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
274 flags = flags | os.O_NONBLOCK
275 fcntl.fcntl(self.write, fcntl.F_SETFL, flags)
276 self.old_wakeup = signal.set_wakeup_fd(self.write)
277
278 def tearDown(self):
279 signal.set_wakeup_fd(self.old_wakeup)
280 os.close(self.read)
281 os.close(self.write)
282 signal.signal(signal.SIGALRM, self.alrm)
283
Brian Curtin3f004b12010-08-06 19:34:52 +0000284@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Christian Heimes8640e742008-02-23 16:23:06 +0000285class SiginterruptTest(unittest.TestCase):
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000286
287 def setUp(self):
288 """Install a no-op signal handler that can be set to allow
289 interrupts or not, and arrange for the original signal handler to be
290 re-installed when the test is finished.
291 """
Brian Curtin3f004b12010-08-06 19:34:52 +0000292 self.signum = signal.SIGUSR1
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000293 oldhandler = signal.signal(self.signum, lambda x,y: None)
294 self.addCleanup(signal.signal, self.signum, oldhandler)
295
296 def readpipe_interrupted(self):
297 """Perform a read during which a signal will arrive. Return True if the
298 read is interrupted by the signal and raises an exception. Return False
299 if it returns normally.
300 """
301 # Create a pipe that can be used for the read. Also clean it up
302 # when the test is over, since nothing else will (but see below for
303 # the write end).
Christian Heimes8640e742008-02-23 16:23:06 +0000304 r, w = os.pipe()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000305 self.addCleanup(os.close, r)
306
307 # Create another process which can send a signal to this one to try
308 # to interrupt the read.
Christian Heimes8640e742008-02-23 16:23:06 +0000309 ppid = os.getpid()
310 pid = os.fork()
311
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000312 if pid == 0:
313 # Child code: sleep to give the parent enough time to enter the
314 # read() call (there's a race here, but it's really tricky to
315 # eliminate it); then signal the parent process. Also, sleep
316 # again to make it likely that the signal is delivered to the
317 # parent process before the child exits. If the child exits
318 # first, the write end of the pipe will be closed and the test
319 # is invalid.
Christian Heimes8640e742008-02-23 16:23:06 +0000320 try:
321 time.sleep(0.2)
322 os.kill(ppid, self.signum)
323 time.sleep(0.2)
324 finally:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000325 # No matter what, just exit as fast as possible now.
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000326 exit_subprocess()
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000327 else:
328 # Parent code.
329 # Make sure the child is eventually reaped, else it'll be a
330 # zombie for the rest of the test suite run.
331 self.addCleanup(os.waitpid, pid, 0)
Christian Heimes8640e742008-02-23 16:23:06 +0000332
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000333 # Close the write end of the pipe. The child has a copy, so
334 # it's not really closed until the child exits. We need it to
335 # close when the child exits so that in the non-interrupt case
336 # the read eventually completes, otherwise we could just close
337 # it *after* the test.
Christian Heimes8640e742008-02-23 16:23:06 +0000338 os.close(w)
339
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000340 # Try the read and report whether it is interrupted or not to
341 # the caller.
Christian Heimes8640e742008-02-23 16:23:06 +0000342 try:
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000343 d = os.read(r, 1)
Christian Heimes8640e742008-02-23 16:23:06 +0000344 return False
345 except OSError as err:
346 if err.errno != errno.EINTR:
347 raise
348 return True
Christian Heimes8640e742008-02-23 16:23:06 +0000349
350 def test_without_siginterrupt(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200351 # If a signal handler is installed and siginterrupt is not called
352 # at all, when that signal arrives, it interrupts a syscall that's in
353 # progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000354 i = self.readpipe_interrupted()
355 self.assertTrue(i)
356 # Arrival of the signal shouldn't have changed anything.
357 i = self.readpipe_interrupted()
358 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000359
360 def test_siginterrupt_on(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200361 # If a signal handler is installed and siginterrupt is called with
362 # a true value for the second argument, when that signal arrives, it
363 # interrupts a syscall that's in progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000364 signal.siginterrupt(self.signum, 1)
365 i = self.readpipe_interrupted()
366 self.assertTrue(i)
367 # Arrival of the signal shouldn't have changed anything.
368 i = self.readpipe_interrupted()
369 self.assertTrue(i)
Christian Heimes8640e742008-02-23 16:23:06 +0000370
371 def test_siginterrupt_off(self):
Victor Stinner3a7f0f02011-05-08 02:10:36 +0200372 # If a signal handler is installed and siginterrupt is called with
373 # a false value for the second argument, when that signal arrives, it
374 # does not interrupt a syscall that's in progress.
Jean-Paul Calderone9c39bc72010-05-09 03:25:16 +0000375 signal.siginterrupt(self.signum, 0)
376 i = self.readpipe_interrupted()
377 self.assertFalse(i)
378 # Arrival of the signal shouldn't have changed anything.
379 i = self.readpipe_interrupted()
380 self.assertFalse(i)
381
382
Brian Curtin3f004b12010-08-06 19:34:52 +0000383@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000384class ItimerTest(unittest.TestCase):
385 def setUp(self):
386 self.hndl_called = False
387 self.hndl_count = 0
388 self.itimer = None
Christian Heimescc47b052008-03-25 14:56:36 +0000389 self.old_alarm = signal.signal(signal.SIGALRM, self.sig_alrm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000390
391 def tearDown(self):
Christian Heimescc47b052008-03-25 14:56:36 +0000392 signal.signal(signal.SIGALRM, self.old_alarm)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000393 if self.itimer is not None: # test_itimer_exc doesn't change this attr
394 # just ensure that itimer is stopped
395 signal.setitimer(self.itimer, 0)
396
397 def sig_alrm(self, *args):
398 self.hndl_called = True
Martin v. Löwis823725e2008-03-24 13:39:54 +0000399
400 def sig_vtalrm(self, *args):
401 self.hndl_called = True
402
403 if self.hndl_count > 3:
404 # it shouldn't be here, because it should have been disabled.
405 raise signal.ItimerError("setitimer didn't disable ITIMER_VIRTUAL "
406 "timer.")
407 elif self.hndl_count == 3:
408 # disable ITIMER_VIRTUAL, this function shouldn't be called anymore
409 signal.setitimer(signal.ITIMER_VIRTUAL, 0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000410
411 self.hndl_count += 1
412
Martin v. Löwis823725e2008-03-24 13:39:54 +0000413 def sig_prof(self, *args):
414 self.hndl_called = True
415 signal.setitimer(signal.ITIMER_PROF, 0)
416
Martin v. Löwis823725e2008-03-24 13:39:54 +0000417 def test_itimer_exc(self):
418 # XXX I'm assuming -1 is an invalid itimer, but maybe some platform
419 # defines it ?
420 self.assertRaises(signal.ItimerError, signal.setitimer, -1, 0)
Christian Heimescc47b052008-03-25 14:56:36 +0000421 # Negative times are treated as zero on some platforms.
422 if 0:
423 self.assertRaises(signal.ItimerError,
424 signal.setitimer, signal.ITIMER_REAL, -1)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000425
426 def test_itimer_real(self):
427 self.itimer = signal.ITIMER_REAL
Martin v. Löwis823725e2008-03-24 13:39:54 +0000428 signal.setitimer(self.itimer, 1.0)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000429 signal.pause()
Martin v. Löwis823725e2008-03-24 13:39:54 +0000430 self.assertEqual(self.hndl_called, True)
431
R. David Murray44546f82010-04-21 01:59:28 +0000432 # Issue 3864, unknown if this affects earlier versions of freebsd also
Gregory P. Smith397cd8a2010-10-17 04:23:21 +0000433 @unittest.skipIf(sys.platform in ('freebsd6', 'netbsd5'),
434 'itimer not reliable (does not mix well with threading) on some BSDs.')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000435 def test_itimer_virtual(self):
436 self.itimer = signal.ITIMER_VIRTUAL
437 signal.signal(signal.SIGVTALRM, self.sig_vtalrm)
438 signal.setitimer(self.itimer, 0.3, 0.2)
439
Mark Dickinson78373472009-10-31 10:39:21 +0000440 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000441 while time.time() - start_time < 60.0:
Mark Dickinson95078872009-10-04 18:47:48 +0000442 # use up some virtual time by doing real work
443 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000444 if signal.getitimer(self.itimer) == (0.0, 0.0):
445 break # sig_vtalrm handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000446 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000447 self.skipTest("timeout: likely cause: machine too slow or load too "
448 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000449
450 # virtual itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000451 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Martin v. Löwis823725e2008-03-24 13:39:54 +0000452 # and the handler should have been called
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000453 self.assertEqual(self.hndl_called, True)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000454
R. David Murray44546f82010-04-21 01:59:28 +0000455 # Issue 3864, unknown if this affects earlier versions of freebsd also
456 @unittest.skipIf(sys.platform=='freebsd6',
457 'itimer not reliable (does not mix well with threading) on freebsd6')
Martin v. Löwis823725e2008-03-24 13:39:54 +0000458 def test_itimer_prof(self):
459 self.itimer = signal.ITIMER_PROF
460 signal.signal(signal.SIGPROF, self.sig_prof)
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000461 signal.setitimer(self.itimer, 0.2, 0.2)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000462
Mark Dickinson78373472009-10-31 10:39:21 +0000463 start_time = time.time()
Stefan Krahf1da973042010-04-20 08:15:14 +0000464 while time.time() - start_time < 60.0:
Mark Dickinson78373472009-10-31 10:39:21 +0000465 # do some work
466 _ = pow(12345, 67890, 10000019)
Martin v. Löwis823725e2008-03-24 13:39:54 +0000467 if signal.getitimer(self.itimer) == (0.0, 0.0):
468 break # sig_prof handler stopped this itimer
Stefan Krahf1da973042010-04-20 08:15:14 +0000469 else: # Issue 8424
Benjamin Peterson9b140f62010-05-15 18:00:56 +0000470 self.skipTest("timeout: likely cause: machine too slow or load too "
471 "high")
Martin v. Löwis823725e2008-03-24 13:39:54 +0000472
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000473 # profiling itimer should be (0.0, 0.0) now
Ezio Melotti19f2aeb2010-11-21 01:30:29 +0000474 self.assertEqual(signal.getitimer(self.itimer), (0.0, 0.0))
Neal Norwitzf5c7c2e2008-04-05 04:47:45 +0000475 # and the handler should have been called
Martin v. Löwis823725e2008-03-24 13:39:54 +0000476 self.assertEqual(self.hndl_called, True)
477
Victor Stinnera9293352011-04-30 15:21:58 +0200478
Victor Stinner35b300c2011-05-04 13:20:35 +0200479class PendingSignalsTests(unittest.TestCase):
480 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200481 Test pthread_sigmask(), pthread_kill(), sigpending() and sigwait()
482 functions.
Victor Stinner35b300c2011-05-04 13:20:35 +0200483 """
Victor Stinnerb3e72192011-05-08 01:46:11 +0200484 def setUp(self):
485 self.has_pthread_kill = hasattr(signal, 'pthread_kill')
486
Victor Stinner35b300c2011-05-04 13:20:35 +0200487 def handler(self, signum, frame):
488 1/0
489
490 def read_sigmask(self):
491 return signal.pthread_sigmask(signal.SIG_BLOCK, [])
492
Victor Stinnerb3e72192011-05-08 01:46:11 +0200493 def can_test_blocked_signals(self, skip):
494 """
495 Check if a blocked signal can be raised to the main thread without
496 calling its signal handler. We need pthread_kill() or exactly one
497 thread (the main thread).
Victor Stinnera9293352011-04-30 15:21:58 +0200498
Victor Stinnerb3e72192011-05-08 01:46:11 +0200499 Return True if it's possible. Otherwise, return False and print a
500 warning if skip is False, or raise a SkipTest exception if skip is
501 True.
502 """
503 if self.has_pthread_kill:
504 return True
Victor Stinnera9293352011-04-30 15:21:58 +0200505
Victor Stinnerf44ce872011-05-03 17:20:31 +0200506 # The fault handler timeout thread masks all signals. If the main
507 # thread masks also SIGUSR1, all threads mask this signal. In this
508 # case, if we send SIGUSR1 to the process, the signal is pending in the
509 # main or the faulthandler timeout thread. Unblock SIGUSR1 in the main
510 # thread calls the signal handler only if the signal is pending for the
Victor Stinnerb3e72192011-05-08 01:46:11 +0200511 # main thread. Stop the faulthandler timeout thread to workaround this
512 # problem.
513 import faulthandler
Victor Stinnerf44ce872011-05-03 17:20:31 +0200514 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner2d4a91e2011-05-03 14:11:22 +0200515
Victor Stinnerb3e72192011-05-08 01:46:11 +0200516 # Issue #11998: The _tkinter module loads the Tcl library which
517 # creates a thread waiting events in select(). This thread receives
518 # signals blocked by all other threads. We cannot test blocked
519 # signals
520 if '_tkinter' in sys.modules:
521 message = ("_tkinter is loaded and pthread_kill() is missing, "
522 "cannot test blocked signals (issue #11998)")
523 if skip:
524 self.skipTest(message)
525 else:
526 print("WARNING: %s" % message)
527 return False
528 return True
529
530 def kill(self, signum):
531 if self.has_pthread_kill:
532 tid = threading.current_thread().ident
533 signal.pthread_kill(tid, signum)
534 else:
535 pid = os.getpid()
536 os.kill(pid, signum)
537
538 @unittest.skipUnless(hasattr(signal, 'sigpending'),
539 'need signal.sigpending()')
540 def test_sigpending_empty(self):
541 self.assertEqual(signal.sigpending(), set())
542
543 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
544 'need signal.pthread_sigmask()')
545 @unittest.skipUnless(hasattr(signal, 'sigpending'),
546 'need signal.sigpending()')
547 def test_sigpending(self):
548 self.can_test_blocked_signals(True)
549
550 signum = signal.SIGUSR1
551 old_handler = signal.signal(signum, self.handler)
552 self.addCleanup(signal.signal, signum, old_handler)
553
554 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
555 self.kill(signum)
556 self.assertEqual(signal.sigpending(), {signum})
557 with self.assertRaises(ZeroDivisionError):
558 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
559
560 @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
561 'need signal.pthread_kill()')
562 def test_pthread_kill(self):
563 signum = signal.SIGUSR1
564 current = threading.current_thread().ident
565
566 old_handler = signal.signal(signum, self.handler)
567 self.addCleanup(signal.signal, signum, old_handler)
568
569 with self.assertRaises(ZeroDivisionError):
570 signal.pthread_kill(current, signum)
571
572 @unittest.skipUnless(hasattr(signal, 'sigwait'),
573 'need signal.sigwait()')
574 def test_sigwait(self):
575 old_handler = signal.signal(signal.SIGALRM, self.handler)
576 self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
577
578 signal.alarm(1)
579 self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)
580
581 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
582 'need signal.pthread_sigmask()')
583 def test_pthread_sigmask_arguments(self):
584 self.assertRaises(TypeError, signal.pthread_sigmask)
585 self.assertRaises(TypeError, signal.pthread_sigmask, 1)
586 self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3)
587 self.assertRaises(OSError, signal.pthread_sigmask, 1700, [])
588
589 @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
590 'need signal.pthread_sigmask()')
591 def test_pthread_sigmask(self):
592 test_blocked_signals = self.can_test_blocked_signals(False)
593 signum = signal.SIGUSR1
Victor Stinner6fd49e12011-05-04 12:38:03 +0200594
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200595 # Install our signal handler
Victor Stinner35b300c2011-05-04 13:20:35 +0200596 old_handler = signal.signal(signum, self.handler)
Victor Stinnera9293352011-04-30 15:21:58 +0200597 self.addCleanup(signal.signal, signum, old_handler)
598
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200599 # Unblock SIGUSR1 (and copy the old mask) to test our signal handler
Victor Stinnera9293352011-04-30 15:21:58 +0200600 old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
601 self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200602 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200603 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200604
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200605 # Block and then raise SIGUSR1. The signal is blocked: the signal
606 # handler is not called, and the signal is now pending
Victor Stinnera9293352011-04-30 15:21:58 +0200607 signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
Victor Stinnerb3e72192011-05-08 01:46:11 +0200608 if test_blocked_signals:
609 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200610
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200611 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200612 blocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200613 self.assertIn(signum, blocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200614 self.assertEqual(old_mask ^ blocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200615
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200616 # Unblock SIGUSR1
Victor Stinnerb3e72192011-05-08 01:46:11 +0200617 if test_blocked_signals:
Victor Stinner6fd49e12011-05-04 12:38:03 +0200618 with self.assertRaises(ZeroDivisionError):
619 # unblock the pending signal calls immediatly the signal handler
620 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
621 else:
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200622 signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
623 with self.assertRaises(ZeroDivisionError):
Victor Stinnerb3e72192011-05-08 01:46:11 +0200624 self.kill(signum)
Victor Stinnera9293352011-04-30 15:21:58 +0200625
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200626 # Check the new mask
Victor Stinner35b300c2011-05-04 13:20:35 +0200627 unblocked = self.read_sigmask()
Victor Stinnera9293352011-04-30 15:21:58 +0200628 self.assertNotIn(signum, unblocked)
Victor Stinner35b300c2011-05-04 13:20:35 +0200629 self.assertEqual(blocked ^ unblocked, {signum})
Victor Stinnera9293352011-04-30 15:21:58 +0200630 self.assertSequenceEqual(old_mask, unblocked)
Victor Stinnerd0e516d2011-05-03 14:57:12 +0200631 # Finally, restore the previous signal handler and the signal mask
Victor Stinnera9293352011-04-30 15:21:58 +0200632
633
Thomas Woutersed03b412007-08-28 21:37:11 +0000634def test_main():
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100635 try:
Victor Stinnerb3e72192011-05-08 01:46:11 +0200636 support.run_unittest(PosixTests, InterProcessSignalTests,
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100637 WakeupSignalTests, SiginterruptTest,
Victor Stinnera9293352011-04-30 15:21:58 +0200638 ItimerTest, WindowsSignalTests,
Victor Stinner35b300c2011-05-04 13:20:35 +0200639 PendingSignalsTests)
Antoine Pitrou8189ab82011-03-20 17:35:32 +0100640 finally:
641 support.reap_children()
Thomas Woutersed03b412007-08-28 21:37:11 +0000642
643
644if __name__ == "__main__":
645 test_main()