views:

531

answers:

2

What are the rules surrounding Python threads and how Unix signals are handled?

Is KeyboardInterrupt, which is triggered by SIGINT but handled internally by the Python runtime, handled differently?

+2  A: 

From the signal documentation:

Some care must be taken if both signals and threads are used in the same program. The fundamental thing to remember in using signals and threads simultaneously is: always perform signal() operations in the main thread of execution. Any thread can perform an alarm(), getsignal(), pause(), setitimer() or getitimer(); only the main thread can set a new signal handler, and the main thread will be the only one to receive signals (this is enforced by the Python signal module, even if the underlying thread implementation supports sending signals to individual threads). This means that signals can’t be used as a means of inter-thread communication. Use locks instead.

Bastien Léonard
+3  A: 

First, when setting up signal handlers using the signal module, you must create them in the main thread. You will receive an exception if you try to create them in a separate thread.

Signal handlers registered via the signal.signal() function will always be called in the main thread. On architectures which support sending signals to threads, at the C level I believe the Python runtime ignores all signals on threads and has a signal handler on the main thread, which it uses to dispatch to your Python-code signal handler.

The documentation for the thread module states that the KeyboardInterrupt exception (which is ordinarily triggered by SIGINT) can be delivered to an arbitrary thread unless you have the signal module available to you, which all Unix systems should have. In that case, it's delivered to the main thread. If you're on a system without signal, you'll have to catch KeyboardInterrupt in your thread and call thread.interrupt_main() to re-raise it in the main thread.

More information can be found in the Python docs for the thread and signal modules.

Joe Shaw
Interesting, I thought only the main thread would receive `KeyboardInterrupt`s.
Bastien Léonard
Yeah! Who knows why it isn't.
Joe Shaw
In my experience, and by my reading of the documentation, when the `signal` module is available, `KeyboardInterrupt` is only delivered to the main thread.
Miles
Miles: Yeah, I think you and Bastien are right. A quick check of some python-list posts and a peek at the code back this up. I've corrected the answer. Thanks!
Joe Shaw