Wann sendet das System ein SIGTERM an einen Prozess?

24

Mein Serverprogramm hat ein SIGTERM empfangen und angehalten (mit Exit-Code 0). Das überrascht mich, denn ich bin mir ziemlich sicher, dass es genügend Speicher dafür gab. Unter welchen Bedingungen sendet Linux (Busybox) ein SIGTERM an einen Prozess?

Michelemarcon
quelle
Ich kann mir keinen Fall vorstellen, in dem der Kernel oder ein Standard-Tool SIGTERM an einen zufälligen Prozess senden würde. Was können Sie uns darüber erzählen, was das Programm macht und wie es gestartet wurde? Wie haben Sie vom Beendigungsstatus des Programms erfahren? Können Sie das Problem reproduzieren? Haben Sie Protokolle, die Sie überprüfen können?
Gilles 'SO- hör auf böse zu sein'
Es liest und schreibt in eine serielle Leitung und antwortet auf UDP- und TCP-Anforderungen. Ich habe die Ausführung in ein Bash-Skript eingebunden und kenne daher den Exit-Code.
Michelemarcon
1
Die Posix-Dokumentation zeigt an, dass SIGTERM ein Ereignis auf Benutzerebene ist. Ist es möglich, dass jemand anderes Ihr Serverprogramm töten konnte?
Shellter
3
Sie sind! Der Rückkehrcode 0 bedeutet einen normalen Ausgang. Wenn es ein SIGTERM $?gäbe , würde es auf 143 (128 + Signalnummer) gesetzt.
Gilles 'SO - hör auf, böse zu sein'
1
^ C ist auch SIGINT, nicht SIGTERM, und das würde mit einem Code von 130
enden

Antworten:

13

Ich werde dies als Antwort posten, damit es eine Lösung gibt, falls sich herausstellt, dass dies das Problem ist.

Ein Beendigungsstatus von 0 bedeutet ein normales Beenden eines erfolgreichen Programms. Ein Programm, das beendet wird, kann eine beliebige Ganzzahl zwischen 0 und 255 als Beendigungsstatus auswählen. Herkömmlicherweise verwenden Programme kleine Werte. Werte 126 und höher werden von der Shell verwendet, um spezielle Bedingungen zu melden. Vermeiden Sie sie daher am besten.

Auf der C-API-Ebene melden Programme einen 16-Bit-Status¹ , der sowohl den Exit-Status des Programms als auch das Signal codiert, das es ggf. beendet hat.

In der Shell setzt sich der Exit-Status eines Befehls (gespeichert in $?) aus dem tatsächlichen Exit-Status des Programms und dem Signalwert zusammen: Wenn ein Programm durch ein Signal beendet wird, $?wird dieser Wert auf einen Wert größer als 128 gesetzt (bei den meisten Shells ist dies der Wert 128 plus die Signalnummer; ATT ksh verwendet 256 + Signalnummer und Yash 384 + Signalnummer, was die Mehrdeutigkeit vermeidet, aber die anderen Shells folgen nicht).

Insbesondere wenn $?0 ist, wird Ihr Programm normal beendet.

Beachten Sie, dass dies den Fall eines Prozesses einschließt, der SIGTERM empfängt, jedoch über einen Signal-Handler verfügt und schließlich normal beendet wird (möglicherweise als indirekte Folge des SIGTERM-Signals, möglicherweise nicht).


Um die Frage in Ihrem Titel zu beantworten, wird SIGTERM vom System niemals automatisch gesendet. Es gibt ein paar Signale, die automatisch gesendet werden, wie SIGHUP, wenn ein Terminal ausgeht, SIGSEGV / SIGBUS / SIGILL, wenn ein Prozess Dinge tut, die er nicht tun sollte, SIGPIPE, wenn er auf eine defekte Pipe / Muffe schreibt, usw. Und es gibt Einige Signale, die aufgrund eines Tastendrucks in einem Terminal gesendet werden, hauptsächlich SIGINT für Ctrl+ C, SIGQUIT für Ctrl+ \und SIGTSTP für Ctrl+ Z, aber SIGTERM gehört nicht dazu. Wenn ein Prozess SIGTERM empfängt, hat ein anderer Prozess dieses Signal gesendet.

¹ grob gesagt

Gilles 'SO - hör auf böse zu sein'
quelle
Gute Erklärung, wie der Ausgangsstatus beim Empfang eines Signals ermittelt wird. Diese Antwort geht jedoch nicht auf die Frage von OP ein.
Codeforester
1
@codeforester Ich habe die Frage im Text beantwortet, nicht die Frage im Titel. Nun, eine der Fragen im Körper - da es auf einem Missverständnis beruhte, ist es ein bisschen chaotisch. Ich werde ein paar Worte über den Rest hinzufügen.
Gilles 'SO- hör auf böse zu sein'
Das kommt auf die Schale an. In ksh93 sind es 256 + signum, in yash 384 + signum
Stéphane Chazelas
Beachten Sie, dass die Verwendung eines Werts über 256 a la ksh nicht unbedingt besser ist, da dies die Übergabe an verhindert exit. Der yashAnsatz ist ein guter Kompromiss, aber siehe RC für einen anderen. Siehe auch Standard-Exit-Code, wenn der Prozess beendet wird.
Stéphane Chazelas
10

SIGTERM ist das Signal, das normalerweise zum administrativen Beenden eines Prozesses verwendet wird.

Dies ist kein Signal, das der Kernel senden würde, sondern das Signal, das ein Prozess normalerweise sendet, um einen anderen Prozess (ordnungsgemäß) zu beenden.

Das ist das Signal , das von den standardmäßig gesendet wird kill, pkill, killall, fuser -k... Befehle.

Dies ist das Signal, das an Daemons gesendet wird, um sie zu stoppen (wie bei a service some-service stop) oder initvor dem Herunterfahren (gefolgt von SIGKILL für Prozesse, die bei SIGTERM nicht rechtzeitig beendet werden konnten).

Beachten Sie, dass SIGTERM nicht das Signal ist, auf das gesendet wird ^C. Das gesendete Signal ^Cist SIGINT.

Stéphane Chazelas
quelle