Pourquoi ne puis-je pas tuer un processus SIGSTOP avec un SIGTERM et où est stocké le signal en attente?

24

J'utilise Debian stretch (systemd). J'exécutais le démon rsyslog au premier plan en utilisant /usr/sbin/rsyslogd -n et j'ai fait un Ctrl+ Zpour l'arrêter. L'état du processus est passé à Tl(arrêté, fileté). I a délivré plusieurs commandes pour le processus, et l'état du processus a été le même: . Une fois que j'ai fait un , il est mort. J'ai 3 questions.kill -15 <pid>Tlfg

  • Pourquoi le SIGSTOPprocessus -ed n'a-t-il pas répondu SIGTERM? Pourquoi le noyau le maintient-il dans le même état?
  • Pourquoi a-t-il été tué au moment où il a reçu le SIGCONTsignal?
  • Si c'était à cause du SIGTERMsignal précédent , où était-il conservé jusqu'à la reprise du processus?
nohup
la source

Réponses:

41

SIGSTOPet SIGKILLsont deux signaux qui ne peuvent pas être capturés et traités par un processus. SIGTSTPc'est comme SIGSTOPsauf qu'il peut être attrapé et manipulé.

Les signaux SIGSTOPet SIGTSTParrêtent un processus sur ses traces, prêt pour SIGCONT. Lorsque vous envoyez ce processus a SIGTERM, le processus n'est pas en cours d'exécution et il ne peut donc pas exécuter le code pour quitter.

(Il y a aussi SIGTTINet SIGTTOU, qui sont des signaux générés par la couche TTY lorsqu'un travail en arrière-plan essaie de lire ou d'écrire sur le terminal. Ils peuvent être interceptés mais arrêteront (suspendront) le processus, tout comme SIGTSTP. Mais je vais maintenant d'ignorer ces deux pour le reste de cette réponse.)

Votre CtrlZenvoie le processus a SIGTSTP, qui ne semble pas être traité spécialement de quelque manière que ce soit rsyslogd, donc il suspend simplement le processus en attente SIGCONTou SIGKILL.

La solution ici est également d'envoyer SIGCONTaprès votre SIGTERMafin que le processus puisse recevoir et gérer le signal.

Exemple:

sleep 999 &

# Assume we got PID 456 for this process
kill -TSTP 456    # Suspend the process (nicely)
kill -TERM 456    # Terminate the process (nicely). Nothing happens
kill -CONT 456    # Continue the process so it can exit cleanly

La documentation de la bibliothèque GNU C l' explique assez bien, je pense (ma mise en évidence):

Lorsqu'un processus est arrêté, plus aucun signal ne peut lui être délivré tant qu'il n'est pas poursuivi , à l'exception des SIGKILLsignaux et (évidemment) des SIGCONTsignaux. Les signaux sont marqués comme en attente, mais ne sont pas délivrés tant que le processus n'est pas poursuivi. Le SIGKILLsignal provoque toujours la fin du processus et ne peut pas être bloqué, géré ou ignoré. Vous pouvez ignorer SIGCONT, mais cela entraîne toujours la poursuite du processus s'il est arrêté. L'envoi d'un SIGCONTsignal à un processus entraîne la suppression de tout signal d'arrêt en attente pour ce processus. De même, tous les SIGCONTsignaux en attente d'un processus sont rejetés lorsqu'il reçoit un signal d'arrêt

roaima
la source
1
@nohup. réponse étendue, mais essentiellement, "oui; il a géré le que kill -15vous aviez déjà envoyé".
roaima
2
@nohup yes, selon la documentation: «Lorsqu'un processus est arrêté, plus aucun signal ne peut lui être délivré tant qu'il n'est pas poursuivi ... Les signaux sont marqués comme en attente, mais pas délivrés tant que le processus n'est pas poursuivi. »
roaima
1
Voir aussi SIGTTIN et SIGTTOU qui arrêtent aussi les processus
Stéphane Chazelas
1
@ StéphaneChazelas bon point. J'ai ajouté la mention de ceux-ci mais sinon je les ai ignorés. N'hésitez pas à modifier comme bon vous semble.
roaima du
2
@coteyr. Je ne suis pas d'accord: SIGKILLempêche une application de se nettoyer, il SIGTERMest donc préférable d' utiliser dans de nombreux cas (la plupart).
roaima
9

SIGTERMest comme tout autre signal en ce sens qu'il peut être capturé par un processus. La réception du signal fera simplement passer le processus à une routine de gestion de signal spéciale. Pour SIGTERMl'action par défaut sera de mettre fin au processus, mais par exemple, un éditeur peut souhaiter intercepter le signal afin qu'il puisse enregistrer une ébauche de tous les fichiers ouverts avant de mourir. Si le processus est arrêté, il ne peut pas exécuter le gestionnaire de signaux, mais le signal restera en attente jusqu'à ce que le processus se poursuive. Notez que le nombre de signaux envoyés ne sera généralement pas enregistré.

En théorie, le système pourrait savoir si un gestionnaire de signaux est installé pour le processus SIGTERMet le terminer immédiatement sinon. Mais (selon le commentaire de Gilles) POSIX exige que le signal soit suspendu jusqu'à ce que le processus se poursuive via SIGCONT.

ilkkachu
la source
4
Toutes mes excuses, mon commentaire précédent était faux. Lorsqu'un processus est arrêté, aucun signal ne lui est délivré, à l'exception de SIGKILL et SIGCONT. Même si le signal a son action par défaut qui est de tuer le processus, cela est retardé jusqu'à ce que le processus soit repris par un SIGCONT. POSIX rend obligatoire ce comportement.
Gilles 'SO- arrête d'être méchant'