Existe alguma variante do UNIX em que um processo filho morre com seu pai?

40

Eu tenho estudado o comportamento do kernel do Linux há algum tempo, e sempre ficou claro para mim que:

When a process dies, all its children are given back to the init process (PID 1) until they eventually die.

No entanto, recentemente, alguém com muito mais experiência do que eu com o kernel me disse:

When a process exits, all its children also die (unless you use NOHUP in which case they get back to init).

Agora, mesmo que eu não acredite nisso, eu ainda escrevi um programa simples para ter certeza disso. Eu sei que não devo confiar no tempo ( sleep ) para os testes, pois tudo depende do agendamento do processo, mas para este caso simples, acho que é 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;
}

Aqui está a saída do programa, com o resultado ps associado a cada vez que printf fala:

$ ./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).

Agora, como você pode ver, isso se comporta como eu esperava. O processo órfão (436) é devolvido para init (1) até que ele morra.

No entanto, existe algum sistema baseado em UNIX no qual esse comportamento não se aplica por padrão? Existe algum sistema no qual a morte de um processo desencadeie imediatamente a morte de todos os seus filhos?

    
por John WH Smith 02.10.2014 / 00:11

4 respostas

66

When a process exits, all its children also die (unless you use NOHUP in which case they get back to init).

Isso está errado. Completamente errado. A pessoa dizendo que estava enganada ou confundiu uma situação particular com o caso geral.

Existem duas maneiras pelas quais a morte de um processo pode indiretamente causar a morte de seus filhos. Eles estão relacionados ao que acontece quando um terminal é fechado. Quando um terminal desaparece (historicamente porque a linha serial foi cortada devido a um desligamento do modem, atualmente geralmente porque o usuário fechou a janela do emulador de terminal), um sinal SIGHUP é enviado para o processo de controle em execução nesse terminal - normalmente, o shell inicial é iniciado nesse terminal. Conchas normalmente reagem a isso saindo. Antes de sair, os shells destinados ao uso interativo enviam o HUP para cada trabalho que eles iniciaram.

Iniciar um trabalho a partir de um shell com nohup interrompe essa segunda fonte de sinais HUP porque o trabalho então ignorará o sinal e, portanto, não será informado de que morrerá quando o terminal desaparecer. Outras maneiras de quebrar a propagação de sinais HUP do shell para os jobs incluem o uso do disown builtin do shell se ele tiver um (o job é removido da lista de tarefas do shell) e double forking (o shell lança um filho que lança um filho próprio e sai imediatamente; a concha não tem conhecimento de seu neto).

Novamente, os trabalhos iniciados no terminal não acontecem porque o processo pai (o shell) morre, mas porque o processo pai decide matá-los quando é dito para matá-los. E o shell inicial no terminal não morre porque seu processo pai morre, mas porque seu terminal desaparece (o que pode ou não coincidentemente ser porque o terminal é fornecido por um emulador de terminal que é o processo pai do shell).

    
por 02.10.2014 / 00:48
10

When a process exits, all its children also die (unless you use NOHUP in which case they get back to init).

Isso está correto se o processo for um líder de sessão. Quando um líder de sessão morre, um SIGHUP é enviado para todos os membros dessa sessão. Na prática, isso significa seus filhos e seus descendentes.

Um processo se torna líder de sessão chamando setsid . Shells usam isso.

    
por 02.10.2014 / 11:13
-1

Então, o que os pôsteres acima estão dizendo é que as crianças não morrem, o pai mata-as (ou envia um sinal sobre o que elas terminam). Então você pode ter o que você pede, se você programar o pai para (1) manter um registro de todos os seus filhos, e (2) enviar um sinal para todos os seus filhos.

Isto é o que o Shell faz, e deve ser o que o seu processo pai faz. Pode ser necessário capturar o sinal HUP no pai, para que você ainda tenha controle suficiente para matar os filhos.

    
por 02.10.2014 / 12:19
-1

Eu estou perdendo um pouco nas respostas que estão um pouco relacionadas com os pais que estão morrendo: quando um processo escreve em um canal para o qual não há mais nenhum processo de leitura, ele obtém um SIGPIPE. A ação padrão para o SIGPIPE é a rescisão.

Isso pode realmente causar processos para morrer. Na verdade, é a maneira padrão em que o programa yes morre.

Se eu executar

(yes;echo $? >&2)|head -10

no meu sistema, a resposta é

y
y
y
y
y
y
y
y
y
y
141

e 141 é de fato 128 + SIGPIPE:

   SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                 readers

de man 7 signal .

    
por 03.10.2014 / 11:52