registro - demanda de jurisdiccion voluntaria
¿Es posible adoptar un proceso? (2)
No, no hay manera de que pueda hacer cumplir la Reparenting de la manera que ha descrito.
Proceso A fork()
s proceso B.
El proceso A muere y, por lo tanto, init
adopta B.
Un perro guardián crea el proceso C.
¿Es de alguna manera posible que C adopte B desde init
?
Actualización :
¿O sería posible que C adoptara B directamente (cuando A muere), si C se creó antes de que A esté muerto, sin que init
convierta en un padre intermedio de B?
Actualización-1:
También agradecería cualquier comentario sobre por qué tener la posibilidad de adoptar un proceso de la manera que describí sería algo malo o difícil o imposible de implementar.
Actualización-2 : el caso de uso (padres e hijos se refieren a proceso (es)):
Tengo una aplicación que usa un padre para administrar un montón de niños, que dependen de la facilidad de gestión del padre. Para hacer su trabajo, el padre confía en ser notificado por la terminación de un niño, lo que se hace al recibir la señal correspondiente de SIGCHLD
.
Si el padre o la madre fallecen debido a algún accidente (incluido el fallo de segmentación), debo reiniciar toda la "familia", ya que ahora es imposible activar algo en la terminación de un hijo (que también puede deberse a una segfault).
En tal caso, necesito derribar a todos los niños y reiniciar todo el sistema.
Un posible enfoque para evitar esta situación sería tener un proceso de reserva que pueda asumir el papel del padre muerto ... ¡si pudiera recibir nuevamente las señales SIGCHLD
de SIGCHLD
!
No, definitivamente no es posible. No podría implementarse tampoco, sin algunas condiciones desagradables de carrera. Los chicos de POSIX que hacen estas API nunca crearán algo con una condición de carrera inherente, por lo que incluso si no te molesta, tu kernel no lo obtendrá pronto.
Un problema es que los pids se vuelven a usar (¡son un recurso escaso!), Y tampoco se puede obtener un identificador o cerrar uno; es solo un número. Así que, por ejemplo, en algún lugar de tu código, tienes una variable en la que pones el pid del proceso que deseas reparar. Luego llamas a make_this_a_child_of_me(thepid)
. ¿Qué pasaría entonces? ¡Mientras tanto, el otro proceso podría haber salido y el thepid
cambiado para referirse a algún otro proceso! Oops. No puede haber una forma de proporcionar una API make_this_a_child_of_me
sin una gran reestructuración de la forma en que Unix maneja los procesos.
Tenga en cuenta que todo el trato con wait
en pids infantiles es precisamente para evitar este problema: todavía existe un proceso zombie en la tabla de procesos para evitar que se vuelva a utilizar pid. El padre puede referirse a su hijo por su pid, confiando en que el proceso no va a salir y hacer que el hijo sea reutilizado. Si el hijo sale, su pid está reservado hasta que el padre capture SIGCHLD, o lo espere. Una vez que se cosecha el proceso, su pid está en juego inmediatamente para que otros programas comiencen a usarlo cuando se bifurcan, pero se garantiza que el padre ya lo sabrá.
Respuesta a la actualización : considere un esquema más complicado, donde los procesos se repiten para su próximo antecesor. Claramente, esto no se puede hacer en todos los casos, porque a menudo quiere una manera de repudiar a un niño, para asegurarse de evitar zombis. init cumple muy bien ese rol. Por lo tanto, tiene que haber algún modo de que un proceso especifique que tiene la intención de adoptar, o no, a sus nietos (o menos). El problema con este diseño es exactamente el mismo que en la primera situación: todavía se obtienen condiciones de carrera.
Si se hace por pid nuevamente, entonces el abuelo se expone a una condición de carrera: solo el padre es capaz de obtener un pid, por lo que solo el padre sabe realmente con qué proceso va un pid. Debido a que los abuelos no pueden cosechar, no puede estar seguro de que el proceso del nieto no haya cambiado desde el que pretendía adoptar (o desautorizar, dependiendo de cómo funcionaría la API hipotética). Recuerde, en una máquina muy cargada, no hay nada que impida que un proceso sea retirado de la CPU por unos minutos, ¡y una carga completa podría haber cambiado en ese momento! No es ideal, pero POSIX tiene que dar cuenta de ello.
Finalmente, supongamos que esta API no funciona por pid, sino que generalmente dice: "envíame a todos los nietos" o "envíalos a init". Si se invoca después de que se generan los procesos secundarios, entonces se obtienen las condiciones de carrera como antes. Si se llama antes, entonces todo es inútil: deberías poder reestructurar tu aplicación un poco para obtener el mismo comportamiento. Es decir, si usted sabe antes de comenzar a engendrar procesos secundarios que deberían ser los padres de quién, ¿por qué no puede seguir adelante y crearlos de la manera correcta desde el principio? Pipes y IPC realmente pueden hacer todo el trabajo requerido.