Comment est-il possible que kill -9 pour un processus sous Linux n'ait aucun effet?

j'écris un plugin pour mettre en surbrillance les chaînes de texte automatiquement lorsque vous visitez un site web. C'est comme les résultats de recherche de surbrillance, mais automatique et pour beaucoup de mots; il pourrait être utilisé pour les gens avec des allergies pour faire des mots vraiment se démarquer, par exemple, quand ils parcourent un site alimentaire.

mais j'ai un problème. Quand j'essaie de fermer une fenêtre FF vide, ça bloque tout le processus. Quand je tue le processus, toutes les fenêtres disparaissent, mais le processus Firefox reste en vie (parent PID est 1, n'écoute aucun signal, a beaucoup de ressources ouvertes, mange toujours CPU, mais ne bougera pas).

donc deux questions:

  1. Comment est-il possible pour un processus de ne pas écouter kill -9 (ni en tant qu'utilisateur ni en tant que root)?

  2. est-ce que je peux faire autre chose qu'un redémarrage?

[EDIT] C'est le fautif process:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
digulla  16688  4.3  4.2 784476 345464 pts/14  D    Mar28  75:02 /opt/firefox-3.0/firefox-bin

même chose que ps -ef | grep firefox

UID        PID  PPID  C STIME TTY          TIME CMD
digulla  16688     1  4 Mar28 pts/14   01:15:02 /opt/firefox-3.0/firefox-bin

c'est le seul procédé qui reste. Comme vous pouvez le voir, ce n'est pas un zombie, il court! Il n'écoute pas kill -9, peu importe si je tue par PID ou nom! Si j'essaie de me connecter avec strace , alors le strace est suspendu et ne peut pas être tué. Il n'y a pas de sortie, soit. À mon avis, est-ce que FF est accroché à une certaine routine du noyau, mais laquelle?

[Edit 2] Basé sur le feedback de sigjuice:

ps axopid,comm,wchan

peut vous montrer dans quelle routine du noyau un processus est suspendu. Dans mon cas, le plugin incriminé était L'indexeur Beagle (openSUSE 11.1). Après avoir désactivé le plugin, FF était à nouveau un renard rapide et heureux.

64
demandé sur Aaron Digulla 2009-03-29 18:39:21

7 réponses

tel que noté dans les commentaires à L'OP, un État de processus ( STAT ) de D indique que le processus est dans un État de" sommeil ininterrompu". En termes réels, cela signifie généralement qu'il attend l'arrivée des e/s et qu'il ne peut ou ne veut rien faire - y compris mourir - tant que l'opération d'e/s n'est pas terminée.

Les processus

dans un État D ne seront normalement présents que pendant une fraction de seconde avant la fin de l'opération et ils reviendront à R / S . D'après mon expérience, si un processus est bloqué dans D , il s'agit le plus souvent d'essayer de communiquer avec un NFS inaccessible ou un autre système de fichiers distant, d'essayer d'accéder à un disque dur défaillant, ou de faire usage d'une pièce de matériel par le biais d'un pilote de périphérique flasque. Dans de tels cas, la seule façon de récupérer et de permettre au processus de mourir est soit de remettre le fs/drive/hardware en marche pour que l'E/S puisse terminer, soit d'abandonner et de redémarrer le système. Dans le cas particulier de NFS, le montage peut aussi éventuellement s'arrêter et revenir de l'opération d'E/S (avec un code de défaillance), mais cela dépend des options de montage et il est très courant que les montages NFS soient définis pour attendre éternellement.

c'est distinct d'un processus zombie, qui aura un statut de Z .

124
répondu Dave Sherohman 2009-03-31 14:07:48

vérifiez que le parent-id est vraiment 1. Si non, et c'est firefox , essayez d'abord de sudo killall -9 firefox-bin . Après cela, essayez de tuer le processus spécifique IDs individuellement avec sudo killall -9 [process-id] .

Comment est-il possible pour un processus de ne pas écouter kill -9 (neiter en tant qu'utilisateur ou root)?

si un processus est allé <defunct> et devient alors un zombie avec un parent de 1, vous ne pouvez pas le tuer manuellement; seulement init peut. Les processus zombies sont déjà morts et partis - ils ont perdu la possibilité d'être tués car ils ne sont plus des processus, seulement une entrée de table de processus et son code de sortie associé, en attente d'être collecté. Vous devez tuer le parent, et vous ne pouvez pas tuer init pour des raisons évidentes.

mais voir ici pour plus d'Informations générales. Un redémarrage sera tuer tout, naturellement.

8
répondu John Feminella 2009-03-31 22:51:35

est-il possible que ce processus soit redémarré (par exemple par init) juste au moment où vous le tuez?

Vous pouvez le vérifier facilement. Si le PID est le même après kill -9 PID alors le processus n'a pas été tué, mais s'il a changé le processus a été redémarré.

1
répondu Georg Schölly 2009-03-29 15:12:27

je me suis récemment pris au piège dans un piège de double fourche et avait atterri à cette page avant de finalement trouver ma réponse. Les symptômes sont identiques, même si le problème n'est pas la même:

  • WYKINWYT :Ce que Vous Tuer n'Est Pas Ce que Vous avez Pensé

le code d'essai minimal est montré ci-dessous basé sur un exemple pour un démon SNMP

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc, char* argv[])
{
    //We omit the -f option (do not Fork) to reproduce the problem
    char * options[]={"/usr/local/sbin/snmpd",/*"-f","*/-d","--master=agentx", "-Dagentx","--agentXSocket=tcp:localhost:1706",  "udp:10161", (char*) NULL};

    pid_t pid = fork();
    if ( 0 > pid ) return -1;

    switch(pid)
    {
        case 0: 
        {   //Child launches SNMP daemon
            execv(options[0],options);
            exit(-2);
            break;
        }
        default: 
        {
            sleep(10); //Simulate "long" activity

            kill(pid,SIGTERM);//kill what should be child, 
                              //i.e the SNMP daemon I assume
            printf("Signal sent to %d\n",pid);

            sleep(10); //Simulate "long" operation before closing
            waitpid(pid);
            printf("SNMP should be now down\n");

            getchar();//Blocking (for observation only)
            break;
        }
    }
    printf("Bye!\n");
}

au cours de la première phase le principal processus (7699) lance le démon SNMP (7700) mais on peut voir que celui-ci est maintenant Défunte/Zombie . À côté nous pouvons voir un autre processus (7702) avec les options nous avons spécifié

[nils@localhost ~]$ ps -ef | tail
root       7439      2  0 23:00 ?        00:00:00 [kworker/1:0]
root       7494      2  0 23:03 ?        00:00:00 [kworker/0:1]
root       7544      2  0 23:08 ?        00:00:00 [kworker/0:2]
root       7605      2  0 23:10 ?        00:00:00 [kworker/1:2]
root       7698    729  0 23:11 ?        00:00:00 sleep 60
nils       7699   2832  0 23:11 pts/0    00:00:00 ./main
nils       7700   7699  0 23:11 pts/0    00:00:00 [snmpd] <defunct>
nils       7702      1  0 23:11 ?        00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils       7727   3706  0 23:11 pts/1    00:00:00 ps -ef
nils       7728   3706  0 23:11 pts/1    00:00:00 tail

après la simulation de 10 Secondes nous allons essayer de tuer le seul processus que nous connaissons (7700). Ce que nous réussissons enfin avec waitpid() . Mais le processus 7702 est toujours là

[nils@localhost ~]$ ps -ef | tail
root       7431      2  0 23:00 ?        00:00:00 [kworker/u256:1]
root       7439      2  0 23:00 ?        00:00:00 [kworker/1:0]
root       7494      2  0 23:03 ?        00:00:00 [kworker/0:1]
root       7544      2  0 23:08 ?        00:00:00 [kworker/0:2]
root       7605      2  0 23:10 ?        00:00:00 [kworker/1:2]
root       7698    729  0 23:11 ?        00:00:00 sleep 60
nils       7699   2832  0 23:11 pts/0    00:00:00 ./main
nils       7702      1  0 23:11 ?        00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils       7751   3706  0 23:12 pts/1    00:00:00 ps -ef
nils       7752   3706  0 23:12 pts/1    00:00:00 tail

après avoir donné un caractère au getchar() fonction de nos principaux processus se termine, mais le démon SNMP avec le pid 7002 est toujours là

[nils@localhost ~]$ ps -ef | tail
postfix    7399   1511  0 22:58 ?        00:00:00 pickup -l -t unix -u
root       7431      2  0 23:00 ?        00:00:00 [kworker/u256:1]
root       7439      2  0 23:00 ?        00:00:00 [kworker/1:0]
root       7494      2  0 23:03 ?        00:00:00 [kworker/0:1]
root       7544      2  0 23:08 ?        00:00:00 [kworker/0:2]
root       7605      2  0 23:10 ?        00:00:00 [kworker/1:2]
root       7698    729  0 23:11 ?        00:00:00 sleep 60
nils       7702      1  0 23:11 ?        00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils       7765   3706  0 23:12 pts/1    00:00:00 ps -ef
nils       7766   3706  0 23:12 pts/1    00:00:00 tail

Conclusion

le fait que nous ayons ignoré le mécanisme double fourche nous a fait penser que l'action de tuer n'a pas réussi. Mais en fait, nous avons simplement tué le mauvais processus !!

en ajoutant l'option - f (do Not (Double) Fork ) all go comme prévu

1
répondu NGI 2017-11-14 23:27:42

ps-ef / grep firefox; et vous pouvez voir 3 processus, de les tuer tous.

0
répondu 2009-03-29 14:44:02
sudo killall -9 firefox

devrait fonctionner

EDITION: [PID] a changé de firefox

0
répondu karim79 2009-03-29 15:04:16

vous pouvez aussi faire un pstree et tuer le parent. Cela fait en sorte que vous obtenez l'arbre entier de processus offensant et pas seulement la feuille.

0
répondu Eric Holmberg 2009-03-29 15:09:47