Respuesta corta: no es posible matar un proceso "zombie", porque ya está muerto. Pero sí es posible matar al jefe de los vampiros.

En sistemas operativos de la familia Unix, puede ocurrir que un proceso sea marcado como "zombie" o "difunto". Esta es una situación anormal. Haciendo una analogía terrible, tener procesos "zombie" en un sistema Unix, es como tener cadáveres pudriéndose en las calles. Es decir, muertos sin sepultar. Por ello han sido llamados zombies.

Esto ocurre cuando un proceso finaliza su ejecución (termina), pero su padre (proceso que inició al proceso zombie) no está esperando por su finalización (no recibe el código de retorno). Un proceso "zombie" no existe como tal, ya no está en memoria y no utiliza CPU. Pero el núcleo del sistema operativo aún mantiene información acerca del mismo, el estado de salida o código de retorno, y está esperando que el proceso padre la reclame.

Entonces, un proceso "zombie" es una simple entrada en la tabla de procesos del núcleo del sistema operativo. Lo cual implica que no es posible matar un proceso "zombie", porque ya está muerto. Por más que se le envíen señales como kill -"hachazo en la cabeza", no va a desaparecer (digamos que no ocurre como en las series de zombies).

En este escenario hay dos alternativas: 1- el proceso padre finaliza y los procesos zombies son heredados por init, quien se encarga de recolectarlos y eliminarlos (reclamar su estado para que desaparezcan de la tabla de procesos del núcleo del sistema operativo); 2- Matar al proceso padre para forzar su desaparición.

La solución típica a este problema suele ser la segunda alternativa: matar al proceso padre para que desaparezcan los procesos zombies.

En general, los procesos zombies están asociados a malas prácticas de programación o falta de robustez de un programa. Cuando un proceso lanza procesos hijos, debe hacerse responsable por ellos, es decir, estar listo y esperar su eventual finalización, por más que no ellos no estén pensados para finalizar nunca.

De acuerdo al manual de ps en sistemas operativos GNU/Linux:

    Los procesos marcados como difuntos (<defunct>) son procesos muertos (llamados "zombies"). Estos procesos permanecen en el sistema porque su padre no los ha destruido adecuadamente. Estos procesos serán destruidos por init si el proceso padre finaliza.

En la salida del comando ps se identifican con el estado Z. Procesos finalizados pero no reclamados por sus procesos padres.

De acuerdo al manual de ps en sistemas FreeBSD:

    Un proceso que ha terminado pero su padre no ha esperado por su finalización (en otras palabras, un zombie) es listado como "<defunct>".

Al igual que en la salida del comando ps en sistemas GNU/Linux, un proceso "zombie" se marca con el estado Z.

Ejemplo de un caso real

Se trata de un servidor GNU/Linux corriendo un motor de bases de datos IBM Informix. Por causas anormales, una instancia de base de datos ha generado procesos zombies:

[root@informix666 ~]# ps aux | grep defunct
informix  9665  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
informix  9666  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
informix  9667  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
root      9668  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
root      9669  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
root      9670  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
root      9671  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
root      9672  0.0  0.0      0     0 ?        Z    11:46   0:00 [oninit.exe] <defunct>
root      9831  0.0  0.0    272    20 pts/1    R+   12:14   0:00 grep defunct

Para que desaparezcan estos procesos zombies es necesario matar a todos sus padres. Para ello es necesario conocer el PID (Process ID) de cada padre. Es posible determinar el PID del proceso padre de cada proceso utilizando el comando ps -eo pid,ppid. Por ejemplo, el PID del proceso padre del proceso cuyo PID es 9665 es 9664:

[root@informix666 ~]# ps -eo pid,ppid | grep 9665
 9665  9664

Así, es posible agregar la clave "command" y filtrar por "defunct":

[root@informix666 ~]# ps -eo pid,ppid,command | grep defunct
 9665  9664 [oninit.exe] <defunct>
 9666  9664 [oninit.exe] <defunct>
 9667  9664 [oninit.exe] <defunct>
 9668  9664 [oninit.exe] <defunct>
 9669  9664 [oninit.exe] <defunct>
 9670  9664 [oninit.exe] <defunct>
 9671  9664 [oninit.exe] <defunct>
 9672  9664 [oninit.exe] <defunct>

Se observa que el padre para todos estos procesos zombies es el mismo: aquel cuyo PID es 9664.

En la versión de ps de GNU/Linux, también es posible recurrir a la opción l para mostrar la salida utilizando el formato largo de BSD. Esta salida incluye el PID del proceso padre para cada proceso (cuarta columna):

ps axl

Se observa que el proceso padre de los zombies se encuentra en estado "sleeping". Por ende no se ha enterado de que sus hijos han muerto:

[root@informix666 ~]# ps aux | grep 9664
root      9664  0.0  0.1  74464  1688 ?        S    11:46   0:00 /opt/informix/bin/oninit.exe
root      9837  0.0  0.0   3748   736 pts/1    S+   12:15   0:00 grep 9664

Entonces, o esperamos a que se entere por la sección necrológicas del periódico de mañana, o lo matamos para que no sufra enviándole la señal SIGKILL (kill -9):

[root@informix666 ~]# kill -9 9664

Junto con el proceso padre desaparecen todos los zombies:

[root@informix666 ~]# ps aux | grep defunct
root      9843  0.0  0.0   3748   728 pts/1    S+   12:17   0:00 grep defunct

La respuesta corta era que se debe matar al proceso padre de cada zombie.

Referencias

Linux:

man ps
man -a kill
man 7 signal

FreeBSD:

man ps
man kill
man 3 signal


Tal vez pueda interesarte


Compartí este artículo