Por que a chamada ao sistema waitpid pode ser usada somente com processos filho?

4

A página de manual wait(2) indica que a chamada de sistema waitpid retorna o erro ECHILD se o processo especificado não for filho do processo de chamada. Por que é isso? Esperar em um processo não-filho cria algum tipo de problema de segurança? Existe uma razão técnica pela qual implementar a espera em um processo não-infantil seria difícil ou impossível?

    
por Tanner Swett 09.07.2015 / 18:57

2 respostas

10

Por causa de como waitpid funciona. Em um sistema POSIX, um sinal (SIGCHLD) é entregue a um processo pai quando um de seus processos filhos morre. Em um nível alto, todo o waitpid está fazendo o bloqueio até que um sinal SIGCHLD seja entregue para o processo (ou um dos processos) especificado. Você não pode esperar por processos arbitrários, porque o sinal SIGCHLD nunca seria entregue para eles.

    
por 09.07.2015 / 19:10
3

A resposta de godlygeek é boa para entender como o sistema funciona, mas a pergunta subsequente que inevitavelmente se segue é:

Como determinar se um processo desapareceu?

A maneira correta de esperar em um processo em outro grupo de processos ou sessão é usar kill() . Obviamente, essa é uma resposta não intuitiva. Você não pode usar a família de funções wait porque o sinal SIGCHILD nunca será passado para o seu processo, nem você pode obter o código de status. O kill() , no entanto, pode informar quando um processo específico desapareceu passando 0 para o sinal a ser enviado, que simplesmente verifica se um sinal pode ser enviado para o processo. O valor de retorno de kill() é complexo mas pode ser resumido a isto: Um valor de 0 significa que o processo está ativo e aceitaria sinais de seu processo enquanto um valor de -1 e errno EPERM significa que o processo está ativo mas não aceitando sinais do seu processo.

Alguns exemplos de código C que são verificados uma vez por segundo para verificar se um processo arbitrário desapareceu:

int res = kill(pid, 0);
while (res == 0 || (res < 0 && errno == EPERM))
{
    sleep(1);

    res = kill(pid, 0);
}

Você também pode experimentar o comando kill :

kill -0 <pid>

Isso passará pid e 0 em kill() . Alguns shells têm um kill integrado, por isso é muito mais eficiente do que iniciar um novo processo (por exemplo, ps ).

    
por 17.05.2016 / 13:32