Tuer un processus suspendu?

17

J'ai été légèrement dérouté par:

% vim tmp
zsh: suspended   vim tmp
% kill %1
% jobs
[1]  + suspended   vim tmp
% kill -SIGINT %1
% jobs
[1]  + suspended   vim tmp
% kill -INT %1
% jobs
[1]  + suspended   vim tmp

J'ai donc démissionné pour "le faire moi-même" et je me demande pourquoi plus tard:

% fg
[1]  - continued   vim tmp
Vim: Caught deadly signal TERM
Vim: Finished.
zsh: terminated   vim tmp
%

Oh!

Cela a vraiment du sens, maintenant que j'y pense, cela vimdoit être en cours d'exécution pour que son gestionnaire de signaux soit averti de quitter et de le faire.

Mais évidemment pas ce que je voulais.

Existe-t-il un moyen de "réveiller et quitter" en une seule commande? c'est-à-dire, un alias intégré pour kill %N && fg %N?

Pourquoi la reprise en arrière-plan ne fonctionne-t-elle pas? Si je bgau lieu de fg, Vim reste en vie jusqu'à moi fg, ce qui brise mon intuition ci-dessus.

OJFord
la source

Réponses:

20

vi-vi-viest du diable. Vous devez le tuer avec le feu. Ou SIGKILL:

kill -KILL %1

Les commandes intégrées killsont assez aimables pour envoyer SIGCONTaux processus suspendus afin que vous n'ayez pas à le faire vous-même, mais cela n'aidera pas si le processus bloque le signal que vous envoyez ou si la manipulation du signal entraîne la suspension des processus à nouveau (si un processus d'arrière-plan tente de lire à partir du terminal, par défaut, il sera envoyé SIGTTIN, ce qui suspend le processus s'il n'est pas géré).

PSkocik
la source
1
Pourquoi diable utiliseriez-vous SIGABRT? Il est destiné à indiquer un bug de programme. SIGKILL est ici puisque vous voulez tuer le programme maintenant, qu'il le veuille ou non.
Gilles 'SO- arrête d'être méchant'
1
En fait, il semble que le SIGTERMprocessus de veille se réveille maintenant, du moins s'ils n'ont pas de gestionnaires pour cela. Je pense que cela ne fonctionnait pas de cette façon, car je me souviens avoir dû bgou fgquelque chose avant de recevoir le signal et de s'en aller. Mais j'ai testé avec awk 'BEGIN{while(42){}}' &, et strace kill $!, et il n'y a qu'un seul kill(2)appel système, avec SIGTERM.
Peter Cordes
6

viminstalle des gestionnaires de signaux (et probablement aussi des paramètres sigprocmask(2)) pour ignorer les signaux communs afin que les fichiers en cours de modification ne soient pas perdus en raison d'un contrôle parasite + c ou d'un signal de suppression aléatoire. Un programme plus simple est facilement tué:

% cat busyloop.c
int main(void) {
for (;;) { ; }
return 0;
}
% make busyloop
cc     busyloop.c  -o busyloop
% ./busyloop
^Z
zsh: suspended  ./busyloop
% kill %1
%
[1]  + terminated  ./busyloop

Faire une vimsortie (en toute sécurité) nécessiterait un gestionnaire de signaux vimqui accepte TERMou USR1ou quelque chose, enregistre (ou rejette?) Tous les tampons, etc. Qu'est-ce que vous essayez de faire pour avoir besoin de faire une vimsortie comme ça?

branler
la source
"Qu'est-ce que tu essayes de faire pour avoir besoin de faire sortir Vim comme ça?" - rien, c'était un fichier vraiment "tmp" que je montais. vimn'était qu'un choix de programme mal conçu pour tester la suspension.
OJFord
1
"ignorer les signaux communs afin que tous les fichiers en cours d'édition ne soient pas perdus en raison d'un contrôle parasite + c ou d'un signal de suppression aléatoire" - mais dès que je fgl'ai quitté, il ne s'est arrêté que tant qu'il a été suspendu?
OJFord
2
@OllieFord: ne SIGKILLréveille qu'un processus de sommeil afin qu'il puisse mourir. L'envoi de signaux à un processus suspendu doté de gestionnaires personnalisés ne le réveille pas. (À part SIGCONT, le signal continu, bien sûr. bgEt fgenvoyer SIGCONT.)
Peter Cordes