Pregunta

Supongamos que tengo un proceso que genera exactamente un proceso hijo. Ahora, cuando el proceso padre se cierra por cualquier razón (normal o anormalmente, por kill, ^ C, afirmar falla o cualquier otra cosa) quiero que el proceso hijo muera. ¿Cómo hacer eso correctamente?


Alguna pregunta similar sobre stackoverflow:


Alguna pregunta similar sobre stackoverflow para Windows :

¿Fue útil?

Solución

El niño puede pedirle al núcleo que entregue SIGHUP (u otra señal) cuando el padre muere especificando la opción PR_SET_PDEATHSIG en prctl () syscall de esta manera :

prctl (PR_SET_PDEATHSIG, SIGHUP);

Ver man 2 prctl para más detalles.

Editar: Esto es solo para Linux

Otros consejos

Estoy tratando de resolver el mismo problema, y ??dado que mi programa debe ejecutarse en OS X, la solución solo para Linux no funcionó para mí.

Llegué a la misma conclusión que las otras personas en esta página: no hay una forma compatible con POSIX de notificar a un niño cuando un padre muere. Así que decidí lo siguiente: hacer la encuesta infantil.

Cuando un proceso padre muere (por cualquier motivo), el proceso padre del niño se convierte en el proceso 1. Si el niño simplemente sondea periódicamente, puede verificar si su padre es 1. Si es así, el niño debería salir.

Esto no es genial, pero funciona, y es más fácil que las soluciones de sondeo TCP socket / lockfile sugeridas en otra parte de esta página.

He logrado esto en el pasado ejecutando el " original " código en el "niño" y el " generado " código en el "padre" (es decir: invierte el sentido habitual de la prueba después de fork () ). Luego atrape SIGCHLD en el " generado " código ...

Puede que no sea posible en su caso, pero lindo cuando funciona.

Si no puede modificar el proceso secundario, puede intentar algo como lo siguiente:

int pipes[2];
pipe(pipes)
if (fork() == 0) {
    close(pipes[1]); /* Close the writer end in the child*/
    dup2(0, pipes[0]); /* Use reader end as stdin */
    exec("sh -c 'set -o monitor; child_process & read dummy; kill %1'")
}

close(pipes[0]); /* Close the reader end in the parent */

Esto ejecuta al hijo desde un proceso de shell con control de trabajo habilitado. El proceso hijo se genera en segundo plano. El caparazón espera una nueva línea (o un EOF) y luego mata al niño.

Cuando el padre muere, sin importar la razón, cerrará su extremo de la tubería. El shell secundario obtendrá un EOF de la lectura y procederá a eliminar el proceso secundario en segundo plano.

Por completo. En macOS puedes usar kqueue:

void noteProcDeath(
    CFFileDescriptorRef fdref, 
    CFOptionFlags callBackTypes, 
    void* info) 
{
    // LOG_DEBUG(@"noteProcDeath... ");

    struct kevent kev;
    int fd = CFFileDescriptorGetNativeDescriptor(fdref);
    kevent(fd, NULL, 0, &kev, 1, NULL);
    // take action on death of process here
    unsigned int dead_pid = (unsigned int)kev.ident;

    CFFileDescriptorInvalidate(fdref);
    CFRelease(fdref); // the CFFileDescriptorRef is no longer of any use in this example

    int our_pid = getpid();
    // when our parent dies we die as well.. 
    LOG_INFO(@"exit! parent process (pid %u) died. no need for us (pid %i) to stick around", dead_pid, our_pid);
    exit(EXIT_SUCCESS);
}


void suicide_if_we_become_a_zombie(int parent_pid) {
    // int parent_pid = getppid();
    // int our_pid = getpid();
    // LOG_ERROR(@"suicide_if_we_become_a_zombie(). parent process (pid %u) that we monitor. our pid %i", parent_pid, our_pid);

    int fd = kqueue();
    struct kevent kev;
    EV_SET(&kev, parent_pid, EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
    kevent(fd, &kev, 1, NULL, 0, NULL);
    CFFileDescriptorRef fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd, true, noteProcDeath, NULL);
    CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
    CFRunLoopSourceRef source = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
    CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}

¿El proceso hijo tiene una tubería hacia / desde el proceso padre? Si es así, recibirías un SIGPIPE si escribes, o recibirías EOF al leer, estas condiciones podrían detectarse.

En Linux, puede instalar una señal de muerte principal en el hijo, por ejemplo:

#include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
#include <signal.h> // signals
#include <unistd.h> // fork()
#include <stdio.h>  // perror()

// ...

pid_t ppid_before_fork = getpid();
pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
    ; // continue parent execution
} else {
    int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
    if (r == -1) { perror(0); exit(1); }
    // test in case the original parent exited just
    // before the prctl() call
    if (getppid() != ppid_before_fork)
        exit(1);
    // continue child execution ...

Tenga en cuenta que almacenar la identificación del proceso padre antes de la bifurcación y probarla en el hijo después de prctl () elimina una condición de carrera entre prctl () y la salida del proceso que llamó al hijo.

También tenga en cuenta que la señal de muerte del padre del niño se borra por sí misma en los niños recién creados. No se ve afectado por un execve () .

Esa prueba se puede simplificar si estamos seguros de que el proceso del sistema que está a cargo de adoptar todos los huérfanos tiene PID 1:

pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
    ; // continue parent execution
} else {
    int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
    if (r == -1) { perror(0); exit(1); }
    // test in case the original parent exited just
    // before the prctl() call
    if (getppid() == 1)
        exit(1);
    // continue child execution ...

Sin embargo, confiar en que el proceso del sistema sea init y tener PID 1 no es portátil. POSIX.1-2008 especifica :

  

La ID del proceso principal de todos los procesos secundarios existentes y procesos zombies del proceso de llamada se establecerá en la ID del proceso de un proceso del sistema definido por la implementación. Es decir, estos procesos serán heredados por un proceso especial del sistema.

Tradicionalmente, el proceso del sistema que adopta a todos los huérfanos es PID 1, es decir, init, que es el antepasado de todos los procesos.

En sistemas modernos como Linux o FreeBSD otro proceso podría tener esa función. Por ejemplo, en Linux, un proceso puede llamar a prctl (PR_SET_CHILD_SUBREAPER , 1) para establecerse como un proceso del sistema que hereda todos los huérfanos de cualquiera de sus descendientes (cf. an ejemplo en Fedora 25).

Inspirado por otra respuesta aquí, se me ocurrió la siguiente solución de POSIX. La idea general es crear un proceso intermedio entre el padre y el hijo, que tiene un propósito: observar cuándo muere el padre y matar explícitamente al niño.

Este tipo de solución es útil cuando el código en el elemento secundario no se puede modificar.

int p[2];
pipe(p);
pid_t child = fork();
if (child == 0) {
    close(p[1]); // close write end of pipe
    setpgid(0, 0); // prevent ^C in parent from stopping this process
    child = fork();
    if (child == 0) {
        close(p[0]); // close read end of pipe (don't need it here)
        exec(...child process here...);
        exit(1);
    }
    read(p[0], 1); // returns when parent exits for any reason
    kill(child, 9);
    exit(1);
}

Hay dos pequeñas advertencias con este método:

  • Si matas deliberadamente el proceso intermedio, entonces el niño no será asesinado cuando el padre muera.
  • Si el hijo sale antes que el padre, entonces el proceso intermedio intentará matar al hijo original pid, que ahora podría referirse a un proceso diferente. (Esto podría solucionarse con más código en el proceso intermedio).

Como comentario aparte, el código real que estoy usando está en Python. Aquí está para completar:

def run(*args):
    (r, w) = os.pipe()
    child = os.fork()
    if child == 0:
        os.close(w)
        os.setpgid(0, 0)
        child = os.fork()
        if child == 0:
            os.close(r)
            os.execl(args[0], *args)
            os._exit(1)
        os.read(r, 1)
        os.kill(child, 9)
        os._exit(1)
    os.close(r)

No creo que sea posible garantizar que solo se usen llamadas POSIX estándar. Al igual que la vida real, una vez que se genera un niño, tiene vida propia.

Es posible que el proceso padre detecte la mayoría de los eventos de terminación posibles e intente eliminar el proceso hijo en ese punto, pero siempre hay algunos que no se pueden detectar.

Por ejemplo, ningún proceso puede capturar un SIGKILL . Cuando el núcleo maneja esta señal, matará el proceso especificado sin notificación alguna a ese proceso.

Para extender la analogía: la única otra forma estándar de hacerlo es que el niño se suicide cuando descubre que ya no tiene un padre.

Hay una forma exclusiva de Linux de hacerlo con prctl (2) : vea otras respuestas.

Como han señalado otras personas, confiar en el padre pid para convertirse en 1 cuando el padre sale no es portátil. En lugar de esperar una ID de proceso principal específica, solo espere a que cambie la ID:

pit_t pid = getpid();
switch (fork())
{
    case -1:
    {
        abort(); /* or whatever... */
    }
    default:
    {
        /* parent */
        exit(0);
    }
    case 0:
    {
        /* child */
        /* ... */
    }
}

/* Wait for parent to exit */
while (getppid() != pid)
    ;

Agregue un micro sueño como desee si no desea sondear a toda velocidad.

Esta opción me parece más simple que usar una tubería o confiar en las señales.

Instale un controlador de trampas para detectar SIGINT, que mata el proceso de su hijo si todavía está vivo, aunque otros carteles son correctos de que no detectará SIGKILL.

Abra un archivo .lock con acceso exclusivo y haga que el hijo haga un sondeo al intentar abrirlo; si la apertura tiene éxito, el proceso hijo debería salir

Esta solución funcionó para mí:

  • Pase la tubería estándar al niño: no tiene que escribir ningún dato en la secuencia.
  • El niño lee indefinidamente desde stdin hasta EOF. Un EOF indica que el padre se ha ido.
  • Esta es una manera infalible y portátil de detectar cuando el padre se ha ido. Incluso si el padre falla, el sistema operativo cerrará la tubería.

Esto fue para un proceso de tipo trabajador cuya existencia solo tenía sentido cuando el padre estaba vivo.

Creo que una manera rápida y sucia es crear una tubería entre el niño y el padre. Cuando los padres salgan, los niños recibirán un SIGPIPE.

Algunos carteles ya han mencionado tuberías y kqueue . De hecho, también puede crear un par de zócalos de dominio Unix conectados mediante la llamada socketpair () . El tipo de socket debe ser SOCK_STREAM .

Supongamos que tiene los dos descriptores de archivo de socket fd1, fd2. Ahora fork () para crear el proceso hijo, que heredará los fds. En el padre cierra fd2 y en el niño cierra fd1. Ahora cada proceso puede sondear () el fd abierto restante en su propio extremo para el evento POLLIN . Mientras cada lado no explícitamente close () su fd durante la vida útil normal, puede estar bastante seguro de que una bandera POLLHUP debe indicar la terminación del otro (no importa limpio o no). Al ser notificado de este evento, el niño puede decidir qué hacer (por ejemplo, morir).

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
#include <stdio.h>

int main(int argc, char ** argv)
{
    int sv[2];        /* sv[0] for parent, sv[1] for child */
    socketpair(AF_UNIX, SOCK_STREAM, 0, sv);

    pid_t pid = fork();

    if ( pid > 0 ) {  /* parent */
        close(sv[1]);
        fprintf(stderr, "parent: pid = %d\n", getpid());
        sleep(100);
        exit(0);

    } else {          /* child */
        close(sv[0]);
        fprintf(stderr, "child: pid = %d\n", getpid());

        struct pollfd mon;
        mon.fd = sv[1];
        mon.events = POLLIN;

        poll(&mon, 1, -1);
        if ( mon.revents & POLLHUP )
            fprintf(stderr, "child: parent hung up\n");
        exit(0);
    }
}

Puede intentar compilar el código de prueba de concepto anterior y ejecutarlo en un terminal como ./a.out & amp; . Tiene aproximadamente 100 segundos para experimentar con la eliminación del PID primario mediante varias señales, o simplemente saldrá. En cualquier caso, debería ver el mensaje "niño: el padre colgó".

En comparación con el método que utiliza el controlador SIGPIPE , este método no requiere probar la llamada write () .

Este método también es simétrico , es decir, los procesos pueden usar el mismo canal para monitorear la existencia del otro.

Esta solución solo llama a las funciones POSIX. Intenté esto en Linux y FreeBSD. Creo que debería funcionar en otros Unixes, pero realmente no lo he probado.

Ver también:

  • unix (7) de páginas de manual de Linux, unix (4) para FreeBSD, poll (2) , socketpair ( 2) , socket (7) en Linux.

En POSIX , la salida () , _exit () y _Exit () se definen para:

  • Si el proceso es un proceso de control, la señal SIGHUP se enviará a cada proceso en el grupo de procesos en primer plano del terminal de control que pertenece al proceso de llamada.

Entonces, si organiza que el proceso padre sea un proceso de control para su grupo de procesos, el niño debería recibir una señal SIGHUP cuando salga el padre. No estoy absolutamente seguro de que eso suceda cuando el padre falla, pero creo que sí. Ciertamente, para los casos sin bloqueo, debería funcionar bien.

Tenga en cuenta que es posible que tenga que leer bastante letra pequeña, incluida la sección Definiciones básicas (Definiciones), así como la información de Servicios del sistema para exit () y setsid ( ) y setpgrp () - para obtener la imagen completa. (¡Yo también lo haría!)

Si envía una señal al pid 0, usando por ejemplo

kill(0, 2); /* SIGINT */

esa señal se envía a todo el grupo de proceso, matando efectivamente al niño.

Puede probarlo fácilmente con algo como:

(cat && kill 0) | python

Si presiona ^ D, verá el texto " Terminado " como una indicación de que el intérprete de Python ha sido asesinado, en lugar de simplemente salir debido al cierre de stdin.

En caso de que sea relevante para cualquier otra persona, cuando engendro instancias JVM en procesos secundarios bifurcados de C ++, la única forma en que podía hacer que las instancias JVM terminaran correctamente después de que el proceso padre se completara era hacer lo siguiente. Esperemos que alguien pueda proporcionar comentarios en los comentarios si esta no fuera la mejor manera de hacerlo.

1) Llame a prctl (PR_SET_PDEATHSIG, SIGHUP) en el proceso secundario bifurcado como se sugiere antes de iniciar la aplicación Java a través de execv y

2) Agregue un enlace de apagado a la aplicación Java que sondea hasta que su PID padre sea igual a 1, luego haga un Runtime.getRuntime (). halt (0) . El sondeo se realiza iniciando un shell separado que ejecuta el comando ps (Consulte: ¿Cómo encuentro mi PID en Java o JRuby en Linux? ).

EDITAR 130118:

Parece que no fue una solución sólida. Todavía estoy luchando un poco por comprender los matices de lo que está sucediendo, pero a veces todavía recibía procesos JVM huérfanos cuando ejecutaba estas aplicaciones en sesiones de pantalla / SSH.

En lugar de sondear el PPID en la aplicación de Java, simplemente hice que el gancho de apagado realizara la limpieza seguido de un alto como se indicó anteriormente. Luego me aseguré de invocar waitpid en la aplicación principal de C ++ en el proceso secundario generado cuando llegó el momento de terminar todo. Esta parece ser una solución más sólida, ya que el proceso secundario garantiza que finalice, mientras que el principal utiliza las referencias existentes para asegurarse de que sus hijos finalicen. Compare esto con la solución anterior que hizo que el proceso padre terminara cuando quisiera, y que los niños trataran de averiguar si habían quedado huérfanos antes de terminar.

Si el padre muere, el PPID de los huérfanos cambia a 1; solo necesita verificar su propio PPID. En cierto modo, esta es una encuesta, mencionada anteriormente. aquí hay una pieza de shell para eso:

check_parent () {
      parent=`ps -f|awk '$2=='$PID'{print $3 }'`
      echo "parent:$parent"
      let parent=$parent+0
      if [[ $parent -eq 1 ]]; then
        echo "parent is dead, exiting"
        exit;
      fi
}


PID=$
cnt=0
while [[ 1 = 1 ]]; do
  check_parent
  ... something
done

Encontré 2 soluciones, ambas no perfectas.

1.Mata a todos los niños mediante kill (-pid) cuando recibes la señal SIGTERM.
Obviamente, esta solución no puede manejar '' kill -9 '', pero funciona para la mayoría de los casos y es muy simple porque no necesita recordar todos los procesos secundarios.


    var childProc = require('child_process').spawn('tail', ['-f', '/dev/null'], {stdio:'ignore'});

    var counter=0;
    setInterval(function(){
      console.log('c  '+(++counter));
    },1000);

    if (process.platform.slice(0,3) != 'win') {
      function killMeAndChildren() {
        /*
        * On Linux/Unix(Include Mac OS X), kill (-pid) will kill process group, usually
        * the process itself and children.
        * On Windows, an JOB object has been applied to current process and children,
        * so all children will be terminated if current process dies by anyway.
        */
        console.log('kill process group');
        process.kill(-process.pid, 'SIGKILL');
      }

      /*
      * When you use "kill pid_of_this_process", this callback will be called
      */
      process.on('SIGTERM', function(err){
        console.log('SIGTERM');
        killMeAndChildren();
      });
    }

De la misma manera, puede instalar el controlador 'exit' como se indica arriba si llama a process.exit en algún lugar. Nota: Ctrl + C y bloqueo repentino han sido procesados ??automáticamente por el sistema operativo para eliminar el grupo de proceso, así que no más aquí.

2.Utilice chjj / pty.js para generar su proceso con control terminal conectado.
Cuando matas el proceso actual de todos modos, incluso kill -9, todos los procesos secundarios también se eliminarán automáticamente (¿por el sistema operativo?). Supongo que debido a que el proceso actual tiene otro lado del terminal, por lo que si el proceso actual muere, el proceso secundario obtendrá SIGPIPE, por lo que muere.


    var pty = require('pty.js');

    //var term =
    pty.spawn('any_child_process', [/*any arguments*/], {
      name: 'xterm-color',
      cols: 80,
      rows: 30,
      cwd: process.cwd(),
      env: process.env
    });
    /*optionally you can install data handler
    term.on('data', function(data) {
      process.stdout.write(data);
    });
    term.write(.....);
    */

Logré hacer una solución portátil sin sondeo con 3 procesos al abusar del control de terminal y las sesiones. Esto es masturbación mental, pero funciona.

El truco es:

  • el proceso A se inicia
  • el proceso A crea un tubo P (y nunca lee de él)
  • el proceso A se bifurca en el proceso B
  • el proceso B crea una nueva sesión
  • el proceso B asigna un terminal virtual para esa nueva sesión
  • el proceso B instala el controlador SIGCHLD para morir cuando el niño sale
  • el proceso B establece un controlador SIGPIPE
  • el proceso B se bifurca en el proceso C
  • el proceso C hace lo que sea necesario (por ejemplo, exec () es el binario no modificado o ejecuta cualquier lógica)
  • el proceso B escribe en la tubería P (y bloquea de esa manera)
  • proceso A wait () s en el proceso B y sale cuando muere

De esa manera:

  • si el proceso A muere: el proceso B obtiene un SIGPIPE y muere
  • si el proceso B muere: el proceso A wait () regresa y muere, el proceso C obtiene un SIGHUP (porque cuando el líder de una sesión con una terminal conectada muere, todos los procesos en el grupo de procesos en primer plano obtienen un SIGHUP)
  • si el proceso C muere: el proceso B obtiene un SIGCHLD y muere, entonces el proceso A muere

Deficiencias:

  • el proceso C no puede manejar SIGHUP
  • el proceso C se ejecutará en una sesión diferente
  • el proceso C no puede usar la sesión / API del grupo de procesos porque romperá la configuración frágil
  • crear una terminal para cada operación no es la mejor idea jamás

A pesar de que han pasado 7 años, me he encontrado con este problema, ya que estoy ejecutando la aplicación SpringBoot que necesita iniciar webpack-dev-server durante el desarrollo y debe eliminarlo cuando el proceso de fondo se detiene.

Intento usar Runtime.getRuntime (). addShutdownHook pero funcionó en Windows 10 pero no en Windows 7.

Lo cambié para usar un hilo dedicado que espera a que el proceso se cierre o para InterruptedException que parece funcionar correctamente en ambas versiones de Windows.

private void startWebpackDevServer() {
    String cmd = isWindows() ? "cmd /c gradlew webPackStart" : "gradlew webPackStart";
    logger.info("webpack dev-server " + cmd);

    Thread thread = new Thread(() -> {

        ProcessBuilder pb = new ProcessBuilder(cmd.split(" "));
        pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        pb.directory(new File("."));

        Process process = null;
        try {
            // Start the node process
            process = pb.start();

            // Wait for the node process to quit (blocking)
            process.waitFor();

            // Ensure the node process is killed
            process.destroyForcibly();
            System.setProperty(WEBPACK_SERVER_PROPERTY, "true");
        } catch (InterruptedException | IOException e) {
            // Ensure the node process is killed.
            // InterruptedException is thrown when the main process exit.
            logger.info("killing webpack dev-server", e);
            if (process != null) {
                process.destroyForcibly();
            }
        }

    });

    thread.start();
}

Históricamente, desde UNIX v7, el sistema de proceso ha detectado la orfandad de los procesos al verificar la identificación principal de un proceso. Como digo, históricamente, el proceso del sistema init (8) es un proceso especial por una sola razón: no puede morir. No puede morir porque el algoritmo del núcleo para ocuparse de asignar una nueva identificación de proceso padre depende de este hecho. cuando un proceso ejecuta su llamada exit (2) (mediante una llamada al sistema del proceso o mediante una tarea externa que le envía una señal o similar), el núcleo reasigna a todos los hijos de este proceso la identificación del proceso init como su ID de proceso padre. Esto lleva a la prueba más fácil y la forma más portátil de saber si un proceso se ha quedado huérfano. Simplemente verifique el resultado de la llamada al sistema getppid (2) y si es la identificación del proceso del proceso init (2) , el proceso quedó huérfano antes de la llamada al sistema.

De este enfoque surgen dos problemas que pueden conducir a problemas:

  • primero, tenemos la posibilidad de cambiar el proceso init a cualquier proceso de usuario, entonces ¿Cómo podemos asegurar que el proceso init siempre sea el padre de todos los procesos huérfanos? Bueno, en el código de llamada del sistema exit hay una comprobación explícita para ver si el proceso que ejecuta la llamada es el proceso init (el proceso con pid igual a 1) y, si ese es el caso, el kernel entra en pánico ( Ya no debería poder mantener la jerarquía del proceso), por lo que no está permitido que el proceso de inicio realice una llamada exit (2) .
  • segundo, hay una condición de carrera en la prueba básica expuesta anteriormente. Históricamente, se supone que la identificación del proceso de inicio es 1 , pero eso no está garantizado por el enfoque POSIX, que establece (como se expone en otra respuesta) que solo la identificación del proceso de un sistema está reservada para ese propósito. Casi ninguna implementación posix hace esto, y puede asumir en los sistemas originales derivados de Unix que tener 1 como respuesta de la llamada al sistema getppid (2) es suficiente para asumir que el proceso es huérfano . Otra forma de verificar es hacer un getppid (2) justo después de la bifurcación y comparar ese valor con el resultado de una nueva llamada. Esto simplemente no funciona en todos los casos, ya que ambas llamadas no son atómicas juntas, y el proceso padre puede morir después del fork (2) y antes del primer getppid (2) llamada al sistema. El proceso id padre solo cambia una vez, cuando su padre realiza una llamada exit (2) , por lo que esto debería ser suficiente para verificar si el resultado getppid (2) cambiado entre llamadas para ver que el proceso padre tiene salida. Esta prueba no es válida para los elementos secundarios reales del proceso de inicio, porque siempre son elementos secundarios de init (8) `, pero puede asumir con seguridad que estos procesos tampoco tienen un elemento principal (excepto cuando sustituye en un sistema el proceso init)

Otra forma de hacer esto que es específica de Linux es hacer que el padre se cree en un nuevo espacio de nombres PID. Entonces será PID 1 en ese espacio de nombres, y cuando salga, todos sus hijos serán asesinados inmediatamente con SIGKILL .

Desafortunadamente, para crear un nuevo espacio de nombres PID debe tener CAP_SYS_ADMIN . Pero, este método es muy efectivo y no requiere ningún cambio real para el padre o los hijos más allá del lanzamiento inicial del padre.

Ver clon (2) , pid_namespaces (7) , y unshare (2) .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top