pthreads(7)
описывает, что POSIX.1 требует, чтобы все потоки в атрибутах общего доступа процесса, включая:
POSIX.1 также требует, чтобы некоторые атрибуты были разными для каждого потока, в том числе:
complete_signal
Подпрограмма ядра Linux имеет следующий блок кода - комментарии весьма полезны:
/*
* 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.
*/
Итак, вы видите, что отвечаете за то, куда доставляются сигналы:
Если ваш процесс установил для сигнала значение SIG_IGN
или SIG_DFL
, то сигнал игнорируется (или по умолчанию - kill, core или ignore) для всех потоков.
Если ваш процесс установил расположение сигнала для определенной процедуры-обработчика, вы можете контролировать, какой поток будет получать сигналы, манипулируя масками сигналов определенных потоков, используя pthread_sigmask(3)
. Вы можете назначить один поток для управления ими всеми, или создать один поток для каждого сигнала, или любую комбинацию этих опций для определенных сигналов, или вы полагаетесь на текущее поведение ядра Linux по умолчанию при доставке сигнала в основной поток.
Однако некоторые сигналы являются особыми согласно signal(7)
справочной странице:
Сигнал может быть сгенерирован (и, следовательно, ожидающим) для процесса в целом (например, при отправке с использованием kill (2) ) или для определенного потока (например, определенные сигналы, такие как SIGSEGV и SIGFPE, сгенерированные как следствие выполнения конкретная инструкция на машинном языке направлена на поток, как и сигналы, нацеленные на конкретный поток с помощью
pthread_kill (3) ). Сигнал, управляемый процессом, может быть доставлен в любой из потоков, который в настоящее время не заблокировал сигнал. Если сигнал разблокирован более чем в одном потоке, то ядро выбирает произвольный поток, которому следует доставить сигнал.