J'écris un plugin pour mettre en évidence les chaînes de texte automatiquement lorsque vous visitez un site Web. C'est comme les résultats de recherche en surbrillance mais automatique et pour beaucoup de mots; il pourrait être utilisé par les personnes allergiques pour faire ressortir les mots, par exemple, lorsqu'elles naviguent sur un site alimentaire.
Mais j'ai un problème. Lorsque j'essaie de fermer une fenêtre FF vierge et vide, elle bloque tout le processus. Lorsque je tue le processus, toutes les fenêtres disparaissent, mais le processus Firefox reste actif (le PID parent est 1, n'écoute aucun signal, a beaucoup de ressources ouvertes, continue de manger, mais ne bouge pas).
Donc deux questions:
Comment est-il même possible pour un processus de ne pas écouter kill -9 (ni en tant qu'utilisateur ni en tant que root)?
Est-ce que je peux faire autre chose qu'un redémarrage?
[EDIT] Ceci est le processus incriminé:
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
Idem avec 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 processus qui reste. Comme vous pouvez le constater, ce n'est pas un zombie, c'est la course! Il n'écoute pas pour tuer -9, peu importe si je tue par PID ou par nom! Si j'essaie de me connecter avec strace
, alors la strace
se bloque également et ne peut pas être tuée. Il n'y a pas de sortie non plus. Je suppose que FF se bloque dans une routine du noyau, mais laquelle?
[EDIT2] Basé sur les commentaires de sigjuice:
ps axopid,comm,wchan
peut vous montrer dans quelle routine de noyau un processus est bloqué. Dans mon cas, le plugin incriminé était Beagle Indexer (openSUSE 11.1). Après avoir désactivé le plugin, FF était redevenu un renard rapide et heureux.
Comme indiqué dans les commentaires relatifs au PO, un statut de processus (STAT
) de D
indique que le processus est dans un état de "veille ininterrompue". En termes réels, cela signifie généralement qu'il attend des E/S et ne peut/ne veut rien faire - y compris la mort - jusqu'à ce que l'opération d'E/S soit terminée.
Les processus dans un état D
n'y seront normalement présents que pendant une fraction de seconde avant la fin de l'opération et ils retourneront à R
/S
. D'après mon expérience, si un processus reste bloqué dans D
, il essaie le plus souvent de communiquer avec un système de fichiers NFS inaccessible ou un autre système de fichiers distant, d'essayer d'accéder à un disque dur défaillant ou d'utiliser un composant matériel au moyen d'un pilote de périphérique floconneux. . Dans de tels cas, le seul moyen de récupérer et d’autoriser le processus à mourir est d’obtenir le système fs/drive/hardware de nouveau opérationnel afin que l’E/S puisse se terminer ou d’abandonner et de redémarrer le système. Dans le cas spécifique de NFS, le montage peut également expirer et revenir de l'opération d'E/S (avec un code d'échec), mais cela dépend des options de montage et il est très courant que les montages NFS soient configurés pour attendre indéfiniment .
Ceci est différent d'un processus zombie, qui aura le statut Z
.
Vérifiez bien que l'identifiant parent est vraiment 1. Si ce n'est pas le cas et qu'il s'agit de firefox
, essayez d'abord Sudo killall -9 firefox-bin
. Après cela, essayez de supprimer les ID de processus spécifiques individuellement avec Sudo killall -9 [process-id]
.
Comment est-il même possible pour un processus de ne pas écouter kill -9 (en tant qu'utilisateur ni en tant que root)?
Si un processus a disparu <defunct>
et devient ensuite un zombie avec un parent de 1, vous ne pouvez pas le tuer manuellement; seulement init
can. Les processus zombies sont déjà morts et ont disparu - ils ont perdu la possibilité d'être tués car ils ne sont plus des processus, il ne reste plus qu'une entrée de table de processus et son code de sortie associé, en attente de collecte. 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 va tout tuer, naturellement.
Dernièrement, je me suis retrouvé pris au piège dans Double Fork et je me suis retrouvé sur cette page avant de finalement trouver ma réponse. Les symptômes sont identiques même si le problème n'est pas le même:
Le code de test minimal est présenté ci-dessous à partir d'un exemple de 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 processus principal (7699) lance le démon SNMP (7700) mais nous pouvons voir que celui-ci est désormais Defunct/Zombie. A côté, nous pouvons voir un autre processus (7702) avec les options que nous avons spécifiées
[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 les 10 secondes simulées, nous essaierons de tuer le seul processus connu (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 à la fonction getchar (), notre processus principal 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 fork nous a fait penser que l'action de destruction n'a pas abouti. Mais en fait, nous avons simplement tué le mauvais processus !!
En ajoutant l’option -f (Ne pas (double) fourchette), tout se passe comme prévu
Est-il possible que ce processus soit redémarré (par exemple par init) juste au moment où vous le tuez?
Vous pouvez vérifier cela facilement. Si le PID est identique après kill -9 PID
, le processus n'a pas été arrêté, mais s'il a changé, le processus a été redémarré.
Sudo killall -9 firefox
Devrait marcher
EDIT: [PID] changé en firefox
ps -ef | grep firefox; et vous pouvez voir 3 processus, tuez-les tous.
Vous pouvez également faire un pstree et tuer le parent. Cela garantit que vous obtenez l'intégralité de l'arborescence du processus incriminé et pas seulement la feuille.