Der Eintrag in POSIX zu "Signal Generation and Delivery" in "Rationale:System Interfaces General Information" sagt
Für einen Prozess generierte Signale werden nur an einen Thread geliefert. Wenn also mehr als ein Thread geeignet ist, ein Signal zu empfangen, muss einer ausgewählt werden. Die Wahl der Threads bleibt vollständig der Implementierung überlassen, um sowohl die größtmögliche Bandbreite an konformen Implementierungen zu ermöglichen als auch Implementierungen die Freiheit zu geben, das Signal an den "einfachst möglichen" Thread zu liefern, falls es Unterschiede in der Einfachheit der Lieferung zwischen verschiedenen Threads geben sollte.
Aus dem signal(7)
Handbuch auf einem Linux-System:
Ein Signal kann für einen Prozess als Ganzes generiert (und somit anstehend) werden (z. B. wenn es mit kill(2)
gesendet wird). ) oder für einen bestimmten Thread (z. B. sind bestimmte Signale wie SIGSEGV und SIGFPE, die als Folge der Ausführung einer bestimmten Maschinensprachanweisung erzeugt werden, Thread-gerichtet, da Signale, die unter Verwendung von pthread_kill(3)
auf einen bestimmten Thread gerichtet sind ). Ein prozessgerichtetes Signal kann an jeden der Threads geliefert werden, bei dem das Signal derzeit nicht blockiert ist. Wenn mehr als einer der Threads das Signal entsperrt hat, dann wählt der Kernel einen beliebigen Thread, an den er das Signal liefert.
Und in pthreads(7)
:
Threads haben unterschiedliche alternative Signalstapeleinstellungen. Die alternativen Signalstack-Einstellungen eines neuen Threads werden jedoch von dem Thread kopiert, der ihn erstellt hat, sodass die Threads zunächst einen alternativen Signalstack teilen (behoben in Kernel 2.6.16).
Aus dem pthreads(3)
Handbuch auf einem OpenBSD-System (als Beispiel für einen alternativen Ansatz):
Signal-Handler werden normalerweise auf dem Stack des aktuell ausgeführten Threads ausgeführt.
(Mir ist derzeit nicht bekannt, wie dies gehandhabt wird, wenn mehrere Threads gleichzeitig auf einem Computer mit mehreren Prozessoren ausgeführt werden)
Die ältere LinuxThread-Implementierung von POSIX-Threads erlaubte nur, dass bestimmte einzelne Threads von Signalen angesteuert wurden. Ab pthreads(7)
auf einem Linux-System:
LinuxThreads unterstützt nicht die Vorstellung von prozessgesteuerten Signalen:Signale können nur an bestimmte Threads gesendet werden.
Als Erweiterung der akzeptierten Antwort gibt es eine praktischere Sichtweise, die ich hier gefunden habe.
Die Essenz ist die folgende:
Signal-Handler sind pro Prozess, aber Signalmasken sind pro Thread.
- Wenn wir also einen Signal-Handler (mit signal() oder sigaction()) auf irgendeinem Thread installieren/deinstallieren, wirkt sich das auf alle aus.
- Wenn ein Prozess ein Signal erhält, wird der Handler nur auf einem einzigen Thread ausgeführt. Unter diesen wird pseudozufällig dieser Thread ausgewählt, dessen Signalmaske ihn akzeptiert. Meine Experimente zeigen, dass es immer der Thread mit der geringsten PID ist.
- Signale, die an einen beliebigen Thread gesendet werden, werden als an den Hauptprozess gesendete Signale betrachtet. Wenn also ein Thread ein Signal erhält, ist es durchaus möglich, dass ein anderer Thread den Handler ausführt. Am besten sehen wir das so, als ob Fäden (gekennzeichnet durch
tid
s, Thread-IDs) würden als maskierte Prozesse betrachtet (gekennzeichnet durchpid
). s) und Signale, die antid
gesendet werden an derenpid
weitergeleitet werden . - Für die Ausführung eines Signalhandlers wird in seiner Signalmaske automatisch die angegebene Signalnummer maskiert. Dies dient dazu, die Ausführung eines gestapelten Signal-Handlers in einem Signal-Burst zu verhindern. Dies kann mit dem
SA_NODEFER
geändert werden Flag dessigaction(...)
anrufen. - (3) und (4) ergibt, dass das System im Falle eines Signalbursts die Signalhandler möglichst parallel verteilt.
- Allerdings, wenn wir die sigaction mit
SA_NODEFER
eingerichtet haben , immer derselbe Thread erhält das Signal und sie werden gestapelt .