La voce in POSIX su "Generazione e consegna del segnale" in "Razionale:informazioni generali sulle interfacce di sistema" dice
I segnali generati per un processo vengono consegnati a un solo thread. Pertanto, se più di un thread è idoneo a ricevere un segnale, è necessario sceglierne uno. La scelta dei thread è lasciata interamente all'implementazione sia per consentire la più ampia gamma possibile di implementazioni conformi sia per dare alle implementazioni la libertà di consegnare il segnale al thread "più semplice possibile" in caso di differenze nella facilità di consegna tra i diversi thread.
Da signal(7)
manuale su un sistema Linux:
Un segnale può essere generato (e quindi in sospeso) per un processo nel suo complesso (ad esempio, quando viene inviato utilizzando
kill(2)
) o per un thread specifico (ad esempio, alcuni segnali, come SIGSEGV e SIGFPE, generati come conseguenza dell'esecuzione di una specifica istruzione in linguaggio macchina sono diretti al thread, in quanto sono segnali indirizzati a un thread specifico utilizzandopthread_kill(3)
). Un segnale diretto dal processo può essere consegnato a uno qualsiasi dei thread che non ha attualmente il segnale bloccato. Se più di uno dei thread ha il segnale sbloccato, allora il kernel sceglie un thread arbitrario a cui consegnare il segnale.
E in pthreads(7)
:
I thread hanno impostazioni distinte dello stack di segnale alternativo. Tuttavia, le impostazioni dello stack di segnali alternativo di un nuovo thread vengono copiate dal thread che lo ha creato, in modo che i thread condividano inizialmente uno stack di segnali alternativo (corretto nel kernel 2.6.16).
Dal pthreads(3)
manuale su un sistema OpenBSD (come esempio di un approccio alternativo):
I gestori di segnali vengono normalmente eseguiti sullo stack del thread attualmente in esecuzione.
(Al momento non sono a conoscenza di come viene gestito quando più thread sono in esecuzione contemporaneamente su una macchina multiprocessore)
La vecchia implementazione LinuxThread dei thread POSIX consentiva solo a singoli thread distinti di essere presi di mira dai segnali. Da pthreads(7)
su un sistema Linux:
LinuxThreads non supporta la nozione di segnali diretti dal processo:i segnali possono essere inviati solo a thread specifici.
Estendendo la risposta accettata, c'è una visione più pratica, quella che ho trovato qui.
L'essenza è la seguente:
I gestori di segnale sono per processo, ma le maschere di segnale sono per thread.
- Pertanto, se installiamo/disinstalliamo un gestore di segnale (con signal() o sigaction()) su qualsiasi thread, ciò influenzerà tutti.
- Se un processo riceve un segnale, il gestore verrà eseguito solo su un singolo thread. Questo thread è selezionato in modo pseudo-casuale tra di loro, la cui maschera di segnale lo accetta. I miei esperimenti mostrano che è sempre il thread con il pid minore.
- I segnali inviati a qualsiasi thread sono considerati segnali inviati al processo principale. Pertanto, se un thread riceve un segnale, è possibile che un altro thread esegua il gestore. Meglio se lo vediamo come se i thread (identificati da
tid
s, ID thread) verrebbero considerati come processi mascherati (identificati dapid
s) e segnali inviati a untid
verrebbero inoltrati al loropid
. - Per l'esecuzione di un gestore di segnale, nella sua maschera di segnale viene mascherato automaticamente il numero di segnale dato. Questo per impedire l'esecuzione del gestore di segnali in pila in un burst di segnale. Questo può essere cambiato con
SA_NODEFER
flag delsigaction(...)
chiama. - (3) e (4) risulta che, nel caso di un burst di segnale, il sistema distribuisce i gestori di segnale possibilmente nel modo più parallelo possibile.
- Tuttavia, se abbiamo impostato la sigazione con
SA_NODEFER
, sempre lo stesso thread riceverà il segnale e si accumuleranno .