diff -r 36af3566b67a Lib/test/test_thread.py --- a/Lib/test/test_thread.py Thu Nov 03 15:38:58 2016 +0200 +++ b/Lib/test/test_thread.py Fri Nov 04 11:56:43 2016 -0400 @@ -4,6 +4,7 @@ from test import support thread = support.import_module('_thread') import time +import signal import sys import weakref @@ -147,6 +148,39 @@ time.sleep(0.01) self.assertIn("Traceback", stderr.getvalue()) + @unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()") + def test_interrupt_main(self): + + # fail after 0.1s: expected SIGINTs were not received while spinning + signal.signal(signal.SIGALRM, lambda *args: self.fail("timeout")) + signal.setitimer(signal.ITIMER_REAL, 0.1) + + def cleanup(): + signal.signal(signal.SIGINT, signal.SIG_DFL) + signal.setitimer(signal.ITIMER_REAL, 0) + signal.signal(signal.SIGALRM, signal.SIG_DFL) + self.addCleanup(cleanup) + + # lock: held before interrupt_main(), released when interrupt received + lock = thread.allocate_lock() + + # in this context, "main" is the thread running this test, + # so instead of catching KeyboardInterrupt, we assert receipt of SIGINT + signal.signal(signal.SIGINT, lambda *args: lock.release()) + + # code below will only complete (not timeout) if SIGINTs received to + # release the lock + + lock.acquire() + thread.interrupt_main() + + while not lock.acquire(0): + time.sleep(0.01) + thread.start_new_thread(thread.interrupt_main, ()) + + while lock.locked(): + time.sleep(0.01) + class Barrier: def __init__(self, num_threads):