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?
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?
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 analarm()
,getsignal()
,pause()
,setitimer()
orgetitimer()
; 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.
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.