single: SIGINT
single: KeyboardInterrupt (built-in exception)
- This function simulates the effect of a :const:`SIGINT` signal arriving --- the
- next time :c:func:`PyErr_CheckSignals` is called, :exc:`KeyboardInterrupt` will
- be raised. It may be called without holding the interpreter lock.
-
- .. % XXX This was described as obsolete, but is used in
- .. % _thread.interrupt_main() (used from IDLE), so it's still needed.
+ Simulate the effect of a :const:`SIGINT` signal arriving. The next time
+ :c:func:`PyErr_CheckSignals` is called, the Python signal handler for
+ :const:`SIGINT` will be called.
+ If :const:`SIGINT` isn't handled by Python (it was set to
+ :data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), this function does
+ nothing.
.. c:function:: int PySignal_SetWakeupFd(int fd)
.. function:: interrupt_main()
- Raise a :exc:`KeyboardInterrupt` exception in the main thread. A subthread can
- use this function to interrupt the main thread.
+ Simulate the effect of a :data:`signal.SIGINT` signal arriving in the main
+ thread. A thread can use this function to interrupt the main thread.
+
+ If :data:`signal.SIGINT` isn't handled by Python (it was set to
+ :data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), this function does
+ nothing.
.. function:: exit()
import weakref
import os
import subprocess
+import signal
from test import lock_tests
from test import support
class BarrierTests(lock_tests.BarrierTests):
barriertype = staticmethod(threading.Barrier)
+
class MiscTestCase(unittest.TestCase):
def test__all__(self):
extra = {"ThreadError"}
support.check__all__(self, threading, ('threading', '_thread'),
extra=extra, blacklist=blacklist)
+
+class InterruptMainTests(unittest.TestCase):
+ def test_interrupt_main_subthread(self):
+ # Calling start_new_thread with a function that executes interrupt_main
+ # should raise KeyboardInterrupt upon completion.
+ def call_interrupt():
+ _thread.interrupt_main()
+ t = threading.Thread(target=call_interrupt)
+ with self.assertRaises(KeyboardInterrupt):
+ t.start()
+ t.join()
+ t.join()
+
+ def test_interrupt_main_mainthread(self):
+ # Make sure that if interrupt_main is called in main thread that
+ # KeyboardInterrupt is raised instantly.
+ with self.assertRaises(KeyboardInterrupt):
+ _thread.interrupt_main()
+
+ def test_interrupt_main_noerror(self):
+ handler = signal.getsignal(signal.SIGINT)
+ try:
+ # No exception should arise.
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ _thread.interrupt_main()
+
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ _thread.interrupt_main()
+ finally:
+ # Restore original handler
+ signal.signal(signal.SIGINT, handler)
+
+
if __name__ == "__main__":
unittest.main()
}
-/* Replacements for intrcheck.c functionality
- * Declared in pyerrors.h
- */
+/* Simulate the effect of a signal.SIGINT signal arriving. The next time
+ PyErr_CheckSignals is called, the Python SIGINT signal handler will be
+ raised.
+
+ Missing signal handler for the SIGINT signal is silently ignored. */
void
PyErr_SetInterrupt(void)
{
- trip_signal(SIGINT);
+ if ((Handlers[SIGINT].func != IgnoreHandler) &&
+ (Handlers[SIGINT].func != DefaultHandler)) {
+ trip_signal(SIGINT);
+ }
}
void