What happens to a multithreaded Linux process if it gets a signal?
The entry in POSIX on "Signal Generation and Delivery" in "Rationale: System Interfaces General Information" says
Signals generated for a process are delivered to only one thread. Thus, if more than one thread is eligible to receive a signal, one has to be chosen. The choice of threads is left entirely up to the implementation both to allow the widest possible range of conforming implementations and to give implementations the freedom to deliver the signal to the "easiest possible" thread should there be differences in ease of delivery between different threads.
From the signal(7)
manual on a Linux system:
A signal may be generated (and thus pending) for a process as a whole (e.g., when sent using
kill(2)
) or for a specific thread (e.g., certain signals, such as SIGSEGV and SIGFPE, generated as a consequence of executing a specific machine-language instruction are thread directed, as are signals targeted at a specific thread usingpthread_kill(3)
). A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
And in pthreads(7)
:
Threads have distinct alternate signal stack settings. However, a new thread's alternate signal stack settings are copied from the thread that created it, so that the threads initially share an alternate signal stack (fixed in kernel 2.6.16).
From the pthreads(3)
manual on an OpenBSD system (as an example of an alternate approach):
Signals handlers are normally run on the stack of the currently executing thread.
(I'm currently not aware of how this is handled when multiple threads are executing concurrently on a multi-processor machine)
The older LinuxThread implementation of POSIX threads only allowed distinct single threads to be targeted by signals. From pthreads(7)
on a Linux system:
LinuxThreads does not support the notion of process-directed signals: signals may be sent only to specific threads.
Extending the accepted answer, there is a more practical view, what I found here.
The essence is the following:
Signal handlers are per-process, but signal masks are per-thread.
- Thus, if we install/uninstall a signal handler (with signal() or sigaction()) on any thread, it will affect all of them.
- If a process gets a signal, the handler will be executed only on a single thread. This thread is pseudo-randomly selected among them, whose signal mask accepts it. My experiments show that it is always the thread with the least pid.
- Signals sent to any thread are considered as signal sent to the main process. Thus, if a thread gets a signal, it is quite possible that an other thread will execute the handler. Best if we see that as if threads (identified by
tid
s, thread ids) would be considered as masked processes (identified bypid
s), and signals sent to atid
would be forwarded to theirpid
. - For the execution of a signal handler, in its signal mask the given signal number is automatically masked. This is to prevent stacked signal handler execution in a signal burst. This can be changed with the
SA_NODEFER
flag of thesigaction(...)
call. - (3) and (4) results that in the case of a signal burst, the system distributes the signal handlers possibly most parallelly.
- However, if we have set up the sigaction with
SA_NODEFER
, always the same thread will get the signal and they will stack.