Quand le système envoie-t-il un SIGTERM à un processus?

24

Mon programme serveur a reçu un SIGTERM et s'est arrêté (avec le code de sortie 0). Je suis surpris par cela, car je suis à peu près sûr qu'il y avait beaucoup de mémoire pour cela. Dans quelles conditions linux (busybox) envoie-t-il un SIGTERM à un processus?

michelemarcon
la source
Je ne peux penser à aucun cas où le noyau ou un outil standard enverrait SIGTERM à un processus aléatoire. Que pouvez-vous nous dire sur ce que fait le programme et comment il a commencé? Comment avez-vous découvert le statut de sortie du programme? Pouvez-vous reproduire le problème? Avez-vous des journaux que vous pouvez consulter?
Gilles 'SO- arrête d'être méchant'
Il lit et écrit sur une ligne série et répond aux requêtes UDP et TCP. J'ai encapsulé l'exécution sur un script bash et donc je connais le code de sortie.
michelemarcon
1
La documentation Posix indique que SIGTERM est strictement un événement de niveau utilisateur. Est-il possible que quelqu'un d'autre ait pu tuer votre programme serveur?
shellter
3
Tu es! Le code retour 0 signifie une sortie normale. S'il y avait un SIGTERM, $?serait réglé sur 143 (128 + numéro de signal).
Gilles 'SO- arrête d'être méchant'
1
En outre, ^ C est SIGINT, pas SIGTERM, et cela se
terminerait

Réponses:

13

Je posterai ceci comme réponse afin qu'il y ait une sorte de résolution si cela s'avère être le problème.

Un état de sortie de 0 signifie une sortie normale d'un programme réussi. Un programme sortant peut choisir n'importe quel entier entre 0 et 255 comme état de sortie. Classiquement, les programmes utilisent de petites valeurs. Les valeurs 126 et supérieures sont utilisées par le shell pour signaler des conditions spéciales, il est donc préférable de les éviter.

Au niveau de l'API C, les programmes signalent un état 16 bits¹ qui code à la fois l'état de sortie du programme et le signal qui l'a tué, le cas échéant.

Dans le shell, l'état de sortie d' une commande (enregistré dans $?) confond l'état de sortie réel du programme et la valeur du signal: si un programme est tué par un signal, il $?est défini sur une valeur supérieure à 128 (avec la plupart des shells, cette valeur est 128 plus le numéro de signal; ATT ksh utilise 256 + numéro de signal et yash utilise 384 + numéro de signal, ce qui évite toute ambiguïté, mais les autres shells n'ont pas emboîté le pas).

En particulier, si $? vaut 0, votre programme s'est terminé normalement.

Notez que cela inclut le cas d'un processus qui reçoit SIGTERM, mais a un gestionnaire de signal pour cela, et finit par se terminer normalement (peut-être comme une conséquence indirecte du signal SIGTERM, peut-être pas).


Pour répondre à la question de votre titre, SIGTERM n'est jamais envoyé automatiquement par le système. Il y a quelques signaux qui sont envoyés automatiquement comme SIGHUP quand un terminal disparaît, SIGSEGV / SIGBUS / SIGILL quand un processus fait des choses qu'il ne devrait pas faire, SIGPIPE quand il écrit sur une pipe / socket cassée, etc. Et il y a quelques signaux envoyés en raison d'une pression sur une touche dans un terminal, principalement SIGINT pour Ctrl+ C, SIGQUIT pour Ctrl+ \et SIGTSTP pour Ctrl+ Z, mais SIGTERM n'en fait pas partie. Si un processus reçoit SIGTERM, un autre processus a envoyé ce signal.

¹ en gros

Gilles 'SO- arrête d'être méchant'
la source
Belle explication de la façon dont l'état de sortie est déterminé lors de la réception d'un signal. Cependant, cette réponse ne répond pas à la question d'OP.
codeforester
1
@codeforester J'ai répondu à la question dans le corps, pas à la question dans le titre. Eh bien, l'une des questions dans le corps - étant donné qu'elle était basée sur un malentendu, c'est un peu compliqué. J'ajouterai quelques mots sur le reste.
Gilles 'SO- arrête d'être méchant'
Cela dépend de la coque. En ksh93, c'est 256 + signum, en yash, c'est 384 + signum
Stéphane Chazelas
Notez que l'utilisation d'une valeur supérieure à 256 a la ksh n'est pas nécessairement meilleure car cela empêche sa transmission exit. L' yashapproche est un bon compromis, mais voir rc pour un autre. Voir aussi Code de sortie par défaut à la fin du processus?
Stéphane Chazelas
10

SIGTERM est le signal qui est généralement utilisé pour terminer administrativement un processus.

Ce n'est pas un signal que le noyau enverrait, mais c'est le signal qu'un processus enverrait généralement pour terminer (gracieusement) un autre processus.

C'est le signal qui est envoyé par défaut par les kill, pkill, killall, fuser -k... commandes.

C'est le signal qui est envoyé aux démons pour les arrêter (comme sur un service some-service stop ), ou envoyé initavant l'arrêt (suivi par SIGKILL pour les processus qui n'ont pas réussi à se terminer à temps sur SIGTERM).

Notez que SIGTERM n'est pas le signal envoyé ^C. Le signal envoyé ^Cest SIGINT.

Stéphane Chazelas
la source