¿Cómo maneja systemd la muerte de un hijo de un proceso administrado?

¿Cómo maneja systemd la muerte de un hijo de un proceso administrado?

¿Cómo se systemdmaneja la muerte de los hijos de los procesos gestionados?

Supongamos que eso systemdinicia el demonio foo, que luego lanza otros tres demonios: bar1, bar2y bar3. ¿Hará systemdalgo foosi bar2termina inesperadamente? Según tengo entendido, bajo Service Management Facility (SMF) en Solaris foose cerraría o reiniciaría si no se indica startdlo contrario cambiando la propiedad ignore_error. ¿ systemdSe comporta diferente?

Edición #1:

He escrito un demonio de prueba para probar systemdel comportamiento. El demonio se llama mother_daemonporque engendra niños.

#include <iostream>
#include <unistd.h>
#include <string>
#include <cstring>

using namespace std;

int main(int argc, char* argv[])
{
  cout << "Hi! I'm going to fork and make 5 child processes!" << endl;

  for (int i = 0; i < 5; i++)
    {
    pid_t pid = fork();

    if (pid > 0)
      {
    cout << "I'm the parent process, and i = " << i << endl;
      }
    if (pid == 0)
      {
      // The following four lines rename the process to make it easier to keep track of with ps
    int argv0size = strlen(argv[0]);
    string childThreadName = "mother_daemon child thread PID: ";
    childThreadName.append( to_string(::getpid()) );
    strncpy(argv[0],childThreadName.c_str(),argv0size + 25);

    cout << "I'm a child process, and i = " << i << endl;
    pause();
    // I don't want each child process spawning its own process
    break;
      }
    }
  pause();
  return 0;
  }

Esto se controla con una systemdunidad llamada mother_daemon.service:

[Unit]
Description=Testing how systemd handles the death of the children of a managed process
StopWhenUnneeded=true

[Service]
ExecStart=/home/my_user/test_program/mother_daemon
Restart=always

La mother_daemon.serviceunidad está controlada por mother_daemon.target:

[Unit]
Description=A target that wants mother_daemon.service
Wants=mother_daemon.service

Cuando ejecuto sudo systemctl start mother_daemon.target(después sudo systemctl daemon-reload) puedo ver el demonio principal y los cinco demonios secundarios.

Matar a uno de los hijos no tiene ningún efecto en el padre, pero matar al padre (y por lo tanto desencadenar un reinicio) sí reinicia a los hijos.

Terminando mother_daemon.targetcon sudo systemctl stop mother_daemon.targetlos niños también.

Creo que esto responde a mi pregunta.

Respuesta1

No es así.

El proceso principal maneja la muerte de sus hijos, de forma normal.

Este es el mundo POSIX. Si el proceso A ha bifurcado a B y el proceso B ha bifurcado a C, D y E; entonces el proceso B es el que ve el estado SIGCHLDy wait()desde la terminación de C, D y E. El proceso A no sabe lo que sucede con C, D y E, y esto es independiente del sistema.

Para que A sea consciente de que C, D y E terminan, tienen que suceder dos cosas.

(Uno puede ser inteligente con kevent()los BSD. Pero esta es una pregunta de Linux).

Respuesta2

systemdtiene el concepto de proceso principal. En la documentación de systemd, esto se denomina "proceso de servicio principal" o simplemente "proceso principal".

Ejemplo 4 en eldocumentación de systemd.servicedescribe tiene el proceso principal se calcula cuando Type=forking.

La documentación Restart=en los documentos systemd.servicedescribir las diferentes posibilidades para cuando se inicia un servicio en relación con el proceso principal.

Aquí está el texto clave del "ejemplo 4" vinculado arriba:

systemd considerará que el servicio está en proceso de inicialización mientras el programa original aún se está ejecutando. Una vez que sale exitosamente y queda al menos un proceso (y RemainAfterExit=no), el servicio se considera iniciado.

A menudo, un demonio tradicional sólo consta de un proceso. Por lo tanto, si solo queda un proceso después de que finaliza el proceso original, systemd considerará ese proceso como el proceso principal del servicio. En ese caso, la variable $MAINPID estará disponible en ExecReload=, ExecStop=, etc.

En caso de que quede más de un proceso, systemd no podrá determinar el proceso principal, por lo que no asumirá que existe uno. En ese caso, $MAINPID no se expandirá a nada. Sin embargo, si el proceso decide escribir un archivo PID tradicional, systemd podrá leer el PID principal desde allí. Configure PIDFile= en consecuencia.

información relacionada