pthreads(7)
descreve que POSIX.1 requer que todos os threads em um processo compartilhem atributos, incluindo:
POSIX.1 também requer que alguns atributos sejam distintos para cada thread, incluindo:
A complete_signal
rotina do kernel Linux possui o seguinte bloco de código - os comentários são bastante úteis:
/*
* Now find a thread we can wake up to take the signal off the queue.
*
* If the main thread wants the signal, it gets first crack.
* Probably the least surprising to the average bear.
*/
if (wants_signal(sig, p))
t = p;
else if (!group || thread_group_empty(p))
/*
* There is just one thread and it does not need to be woken.
* It will dequeue unblocked signals before it runs again.
*/
return;
else {
/*
* Otherwise try to find a suitable thread.
*/
t = signal->curr_target;
while (!wants_signal(sig, t)) {
t = next_thread(t);
if (t == signal->curr_target)
/*
* No thread needs to be woken.
* Any eligible threads will see
* the signal in the queue soon.
*/
return;
}
signal->curr_target = t;
}
/*
* Found a killable thread. If the signal will be fatal,
* then start taking the whole group down immediately.
*/
if (sig_fatal(p, sig) &&
!(signal->flags & SIGNAL_GROUP_EXIT) &&
!sigismember(&t->real_blocked, sig) &&
(sig == SIGKILL || !p->ptrace)) {
/*
* This signal will be fatal to the whole group.
*/
Então, você vê que você está no comando de onde os sinais são entregues:
Se o seu processo definiu a disposição de um sinal para SIG_IGN
ou SIG_DFL
, então o sinal é ignorado (ou padrão - kill, core ou ignore) para todos os threads.
Se o seu processo definiu a disposição de um sinal para uma rotina de tratamento específica, então você pode controlar qual thread receberá os sinais, manipulando máscaras de sinal de thread específicas usando pthread_sigmask(3)
. Você pode nomear um thread para gerenciar todos eles, ou criar um thread por sinal, ou qualquer mistura dessas opções para sinais específicos, ou você pode contar com o comportamento padrão atual do kernel Linux de entregar o sinal ao thread principal.
Alguns sinais, no entanto, são especiais de acordo com a signal(7)
página do manual:
Um sinal pode ser gerado (e, portanto, pendente) para um processo como um todo (por exemplo, quando enviado usando kill (2) ) ou para uma thread específica (por exemplo, certos sinais, como SIGSEGV e SIGFPE, gerados como consequência da execução uma instrução específica em linguagem de máquina é direcionada por thread, assim como sinais direcionados a uma thread específica usando
pthread_kill (3) ). Um sinal direcionado ao processo pode ser entregue a qualquer um dos threads que atualmente não tem o sinal bloqueado. Se mais de um dos encadeamentos tiver o sinal desbloqueado, o kernel escolhe um encadeamento arbitrário para o qual enviar o sinal.