¿Por qué un zombie está esperando a su hijo?

11

Estoy investigando diferentes fuentes, pero no puedo encontrar una buena descripción de la anatomía de la cosecha infantil. Este es un caso simple de lo que me gustaría entender.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

¿Por qué el zombie está esperando al niño?

¿Puedes explicar esto? ¿Necesito saber C y leer el código fuente de Bash para obtener una comprensión más amplia de esto o hay alguna documentación? Ya he consultado:

GNU bash, versión 4.3.42 (1) -release (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP mié 13 de julio 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


fuente
2
Debe tener en cuenta que esto realmente no tiene nada que ver con bash (aparte del hecho de que si elige usar bash como shell, se iniciarán muchos procesos). Otros shells (tcsh, ksh, zsh, & c) inician todos los procesos y ejecutan esencialmente las mismas funciones del sistema operativo para tratar con ellos.
jamesqf
@jamesqf Interesante. Si desea ampliar su comentario en una respuesta completa, sería genial.
1
Excepto que no es realmente una respuesta, solo señala que ha estado buscando la respuesta en los lugares equivocados :-) Cualquier buen libro sobre programación de sistemas * nix debería proporcionar una respuesta mucho mejor de la que podría escribir.
jamesqf

Respuestas:

17

El zombie no está esperando a su hijo. Al igual que cualquier proceso zombie, permanece hasta que su padre lo recolecte.

Debe mostrar todos los procesos involucrados para comprender lo que está sucediendo, y también mirar el PPID. Use esta línea de comando:

ps -t $(tty) -O ppid,pgid

El padre del proceso que estás matando es cat. Lo que sucede es que bash ejecuta el comando de fondo cat <( sleep 100 & wait )en una subshell. Dado que lo único que hace esta subshell es configurar alguna redirección y luego ejecutar un comando externo, esta subshell se reemplaza por el comando externo. Aquí está el resumen:

  • El bash original (12126) llama forkpara ejecutar el comando de fondo cat <( sleep 100 & wait )en un hijo (14247).
    • El elemento secundario (14247) llama pipepara crear una tubería y luego forkpara crear un elemento secundario para ejecutar la sustitución del proceso sleep 100 & wait.
      • El nieto (14248) llama forka ejecutarse sleep 100en segundo plano. Como el nieto no es interactivo, el proceso en segundo plano no se ejecuta en un grupo de proceso separado. Entonces el nieto espera a sleepque salga.
    • El hijo (14247) llama setpgid(es un trabajo en segundo plano en un shell interactivo para que obtenga su propio grupo de procesos) y luego se execveejecuta cat. (Estoy un poco sorprendido de que la sustitución del proceso no esté ocurriendo en el grupo de procesos en segundo plano).
  • Matas al nieto (14248). Se está ejecutando su padre cat, que no sabe nada sobre ningún proceso secundario y no tiene llamadas comerciales wait. Como el padre del nieto no lo cosecha, el nieto se queda como un zombi.
  • Finalmente, catsale, ya sea porque lo matas o porque sleepregresa y cierra la tubería para catver el final de su entrada. En ese punto, el padre del zombi muere, por lo que el zombi es recogido por init y init lo cosecha.

Si cambia el comando a

{ cat <( sleep 100 & wait ); echo done; } &

luego se catejecuta en un proceso separado, no en el hijo del proceso bash original: el primer hijo tiene que quedarse atrás para ejecutarse echo done. En este caso, si matas al nieto, no se queda como un zombie, porque el niño (que todavía está ejecutando bash en ese momento) lo cosecha.

Ver también ¿Cómo asas Linux proceso de zombi y Can tiene un zombi huérfanos? ¿Se molestarán los niños huérfanos cosechando al zombi?

Gilles 'SO- deja de ser malvado'
fuente
También me sorprendió el proceso del grupo. Parece que fue un error y ahora está arreglado en la rama maestra de bash.
PSkocik
"La fiesta original espera a su hijo (14247)". ¿Por qué o de qué manera? Se supone que el niño se ejecuta en segundo plano y no hay una llamada explícita. ¿Cuál es la diferencia entre el bash original (14246) esperando 14247 y 14247 (que se está ejecutando cat) sin esperar 14248 (esperando sleep)? ¿Hay algún recuerdo de quién espera a quién, qué perdió el niño (14247) y qué no lo hizo el bash original (14246), o tal vez una lista de señales como SIGCHLD de quién debería llamarse y 14247 (ahora en ejecución bash) cancelado? saludos a 14248?
1
@tomas Quise decir que el bash original llama waita su hijo, es decir, lo cosecha. Puedo ver cómo esto sería confuso, he eliminado esa frase que ni siquiera estaba en el punto correcto cronológicamente hablando. La información de que un proceso ha muerto va al padre de ese proceso, un proceso no puede "suscribirse" para recibir información sobre la muerte de algún otro proceso.
Gilles 'SO- deja de ser malvado'
6

Zombie no está esperando al niño. En cambio, zombie es el proceso que ya murió (solo o fue asesinado, como en su ejemplo), tenía su código, datos y pila desasignado, y ahora solo contiene su código de salida, esperando que su padre llame wait(2)para recuperarlo (y, por lo tanto, limpiar la entrada del proceso por completo de la tabla de procesos)

En su ejemplo, cuando el sueño termina (o es asesinado), los padres leerán los estados de salida y cosecharán los zombis. Ver arriba mencionado wait(2)para más detalles.

Matija Nalis
fuente