Was passiert mit einem Multithread-Linux-Prozess, wenn er ein Signal erhält?

19

Wenn ein Unix (Posix) -Prozess ein Signal empfängt, wird ein Signalhandler ausgeführt.

Was passiert damit in einem Multithread-Prozess? Welcher Thread empfängt das Signal?

Meiner Meinung nach sollte die Signal-API erweitert werden, um dies zu handhaben (dh der Thread des Signal-Handlers sollte bestimmt werden können), aber auf der Suche nach Informationen im Netz fand ich nur jahrelange Flammen auf der Mailingliste des Linux-Kernels und auf verschiedene Foren. So wie ich es verstanden habe, unterschied sich das Konzept von Linus vom Posix-Standard, und zuerst wurde eine kompatible Ebene erstellt, aber jetzt folgt das Linux dem Posix-Modell.

Wie ist der aktuelle Stand?

Peterh: Setzen Sie Monica wieder ein
quelle
3
Das Duplikat von stackoverflow.com/questions/11679568/… "pthreads (7) beschreibt, dass für POSIX.1 alle Threads in den Attributen einer Prozessfreigabe erforderlich sind, einschließlich der Signaldispositionen"
Steve,
@steve Danke, aber 1) es ist auf einer anderen SE-Seite 2) diese Spezifikation gibt nicht klar an, was genau passieren wird. Was es bedeutet, die Signal-Handler werden auf allen Threads aufgerufen , aber es scheint mir ein bisschen surrealistisch. 3) Diese Antwort gibt nicht an, was Linus 'Modell war und warum / wie es derzeit verwendet wird.
peterh - Wiedereinsetzung von Monica

Antworten:

9

Der Eintrag in POSIX zu " Signalerzeugung und -lieferung " in "Begründung: Allgemeine Informationen zu Systemschnittstellen" lautet

Für einen Prozess generierte Signale werden nur an einen Thread gesendet. Wenn also mehr als ein Thread zum Empfang eines Signals berechtigt ist, muss einer ausgewählt werden. Die Wahl der Threads bleibt der Implementierung überlassen, um sowohl einen möglichst großen Bereich an konformen Implementierungen zu ermöglichen als auch um Implementierungen die Freiheit zu geben, das Signal an den "einfachsten" Thread zu liefern, falls es Unterschiede in der Einfachheit der Lieferung zwischen verschiedenen Threads gibt.

Aus dem signal(7)Handbuch auf einem Linux-System:

Ein Signal kann für einen gesamten Prozess (z. B. beim Senden mit kill(2)) oder für einen bestimmten Thread (z. B. bestimmte Signale wie SIGSEGV und SIGFPE ) generiert werden (und damit anstehen) , die als Folge der Ausführung eines bestimmten maschinellen Prozesses generiert werden. Sprachanweisungen sind thread-gerichtet, ebenso wie Signale, die auf einen bestimmten Thread abzielen (unter Verwendung von pthread_kill(3)). Ein prozessgesteuertes Signal kann an einen der Threads gesendet werden, für den das Signal derzeit nicht blockiert ist. Wenn für mehr als einen der Threads das Signal nicht blockiert ist, wählt der Kernel einen beliebigen Thread aus, an den das Signal gesendet werden soll.

Und in pthreads(7):

Threads haben unterschiedliche alternative Signalstapeleinstellungen. Die Einstellungen für den alternativen Signalstapel eines neuen Threads werden jedoch von dem Thread kopiert, der ihn erstellt hat, sodass die Threads zunächst einen alternativen Signalstapel gemeinsam nutzen (behoben in Kernel 2.6.16).

Aus dem pthreads(3)Handbuch auf einem OpenBSD-System (als Beispiel für einen alternativen Ansatz):

Signalhandler werden normalerweise auf dem Stapel des aktuell ausgeführten Threads ausgeführt.

(Mir ist derzeit nicht bekannt, wie dies gehandhabt wird, wenn mehrere Threads gleichzeitig auf einem Multiprozessor-Computer ausgeführt werden.)

Die ältere LinuxThread-Implementierung von POSIX-Threads erlaubte nur das Targeting einzelner Threads durch Signale. Von pthreads(7)einem Linux-System aus:

LinuxThreads unterstützt den Begriff der prozessgesteuerten Signale nicht: Signale können nur an bestimmte Threads gesendet werden.

Kusalananda
quelle