Como o systemd lida com a morte de um filho de um processo gerenciado?

Como o systemd lida com a morte de um filho de um processo gerenciado?

Como systemdlida com a morte dos filhos dos processos gerenciados?

Suponha que isso systemdinicie o daemon foo, que então inicia três outros daemons: bar1, bar2, e bar3. Fará systemdalguma coisa foose bar2terminar inesperadamente? Pelo que entendi, no Service Management Facility (SMF) no Solaris fooseria eliminado ou reiniciado se você não informasse startdo contrário, alterando a propriedade ignore_error. Comporta systemd-se de maneira diferente?

Edição nº 1:

Eu escrevi um daemon de teste para testar systemdo comportamento de. O daemon é chamado mother_daemonporque gera filhos.

#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;
  }

Isso é controlado com uma systemdunidade chamada 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

A mother_daemon.serviceunidade é controlada por mother_daemon.target:

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

Quando executo sudo systemctl start mother_daemon.target(depois sudo systemctl daemon-reload), posso ver o daemon pai e os cinco daemons filhos.

Matar um dos filhos não tem efeito sobre os pais, mas matar os pais (e, assim, desencadear uma reinicialização) reinicia os filhos.

Parar mother_daemon.targetcom sudo systemctl stop mother_daemon.targetacaba com as crianças também.

Acho que isso responde à minha pergunta.

Responder1

Isso não acontece.

O processo principal trata da morte de seus filhos, de forma normal.

Este é o mundo POSIX. Se o processo A bifurcou B e o processo B bifurcou C, D e E; então o processo B é o que vê o status SIGCHLDe wait()do término de C, D e E. O processo A não tem conhecimento do que acontece com C, D e E, e isso independe do systemd.

Para que A esteja ciente da terminação de C, D e E, duas coisas precisam acontecer.

(É possível ser esperto com kevent()os BSDs. Mas esta é uma questão do Linux.)

Responder2

systemdtem o conceito de um processo principal. Na documentação do systemd, isso é chamado de "processo de serviço principal" ou simplesmente "processo principal".

Exemplo 4 noDocumentação systemd.servicedescreve que o processo principal é calculado quando Type=forking.

A documentação Restart=nos documentos systemd.servicedescrever as diferentes possibilidades de quando um serviço é iniciado em relação ao processo principal.

Aqui está o texto principal do "exemplo 4" vinculado acima:

O systemd considerará o serviço em processo de inicialização enquanto o programa original ainda estiver em execução. Depois que ele for encerrado com êxito e pelo menos um processo permanecer (e RemainAfterExit=no), o serviço será considerado iniciado.

Freqüentemente, um daemon tradicional consiste apenas em um processo. Portanto, se resta apenas um processo após o término do processo original, o systemd considerará esse processo como o processo principal do serviço. Nesse caso, a variável $MAINPID estará disponível em ExecReload=, ExecStop=, etc.

Caso reste mais de um processo, o systemd não será capaz de determinar o processo principal, portanto não assumirá que existe um. Nesse caso, $MAINPID não será expandido para nada. Porém, se o processo decidir escrever um arquivo PID tradicional, o systemd poderá ler o PID principal a partir daí. Por favor, defina PIDFile= adequadamente.

informação relacionada