Llevo bastante tiempo estudiando el comportamiento del kernel de Linux, y siempre me ha quedado claro que:
Cuando un proceso muere, todos sus hijos son devueltos al
init
proceso (PID 1) hasta que finalmente mueren.
Sin embargo, recientemente, alguien con mucha más experiencia que yo con el núcleo me dijo que:
Cuando finaliza un proceso, todos sus elementos secundarios también mueren (a menos que use
NOHUP
en cuyo caso vuelven ainit
).
Ahora, aunque no lo creo, aún escribí un programa simple para asegurarme de ello. Sé que no debería depender del tiempo ( sleep
) para las pruebas, ya que todo depende de la programación del proceso, pero para este caso simple, creo que es bastante suficiente.
int main(void){
printf("Father process spawned (%d).\n", getpid());
sleep(5);
if(fork() == 0){
printf("Child process spawned (%d => %d).\n", getppid(), getpid());
sleep(15);
printf("Child process exiting (%d => %d).\n", getppid(), getpid());
exit(0);
}
sleep(5);
printf(stdout, "Father process exiting (%d).\n", getpid());
return EXIT_SUCCESS;
}
Aquí está la salida del programa, con el ps
resultado asociado cada vez que printf
habla:
$ ./test &
Father process spawned (435).
$ ps -ef | grep test
myuser 435 392 tty1 ./test
Child process spawned (435 => 436).
$ ps -ef | grep test
myuser 435 392 tty1 ./test
myuser 436 435 tty1 ./test
Father process exiting (435).
$ ps -ef | grep test
myuser 436 1 tty1 ./test
Child process exiting (436).
Ahora, como puede ver, esto se comporta como esperaba. El proceso huérfano (436) se devuelve a init
(1) hasta que muere.
Sin embargo, ¿hay algún sistema basado en UNIX en el que este comportamiento no se aplique por defecto? ¿Existe algún sistema en el que la muerte de un proceso desencadene inmediatamente la muerte de todos sus hijos?
nohup
condisown
.disown
es un componente incorporado en algún shell que elimina un trabajo en ejecución de la tabla de trabajos (tomando un argumento como%1
), y el principal efecto secundario útil de eso es que el shell no enviará un SIGHUP al subproceso.nohup
es una utilidad externa que ignora SIGHUP (y hace algunas otras cosas) y luego inicia el comando pasado en su línea de comando.nohup
de hecho ignora la señal antes de que seaexec
el comando.Esto es correcto si el proceso es un líder de sesión. Cuando un líder de sesión muere, se envía un SIGHUP a todos los miembros de esa sesión. En la práctica eso significa sus hijos y sus descendientes.
Un proceso se convierte en líder de la sesión llamando
setsid
. Las conchas usan esto.fuente
fork
, proceso de matar a los padres,setsid
) y bifurqué a otro niño en esta nueva sesión. Sin embargo, cuando el proceso de los padres (nuevo líder de sesión) murió, el niño no recibió SIGHUP y se apegóinit
hasta que finalmente salió.setpgid(2)
manual: si una sesión tiene un terminal de control, y el indicador CLOCAL para ese terminal no está configurado, y se produce un bloqueo del terminal, entonces el líder de la sesión recibe un SIGHUP. Si el líder de la sesión sale, también se enviará una señal SIGHUP a cada proceso en el grupo de procesos en primer plano del terminal de control.Entonces, lo que dicen los carteles anteriores es que los niños no mueren, los padres los matan (o les envían una señal en la que terminan). Para que pueda tener lo que pide, si programa al padre para (1) mantener un registro de todos sus hijos y (2) enviar una señal a todos sus hijos.
Esto es lo que hace el Shell, y debería ser lo que hace el proceso principal. Puede ser necesario captar la señal HUP en el padre para que todavía tenga el control suficiente para matar a los niños.
fuente
Me faltan un poco en las respuestas que están ligeramente relacionadas con los padres moribundos: cuando un proceso escribe en una tubería para la que ya no hay un proceso de lectura, obtiene un SIGPIPE. La acción estándar para SIGPIPE es la terminación.
De hecho, esto puede causar que los procesos mueran. De hecho, es la forma estándar en que el programa
yes
muere.Si ejecuto
en mi sistema, la respuesta es
y 141 es de hecho 128 + SIGPIPE:
de
man 7 signal
.fuente