Quando um processo termina, o PPID de seus filhos é definido como 1 (adoção pelo init), mas o PGID (identificador do grupo de processos) e o SID (identificador de sessão) não mudam.
Os filhos do processo provavelmente não alteram seu grupo de processos, a menos que sejam destinados a serem daemons. Supondo que não, inicie o processo a ser testado em seu próprio grupo de processos. Chame setpgid(getpid(), getpid()) de sua estrutura de teste, depois de bifurcar e antes de chamar execve para executar o programa que está sendo testado. Chame kill(-test_program_pid, 0) ( kill com um argumento pid negativo e o valor do sinal 0) para testar se existe um processo em execução com o PGID test_program_pid . Passe SIGKILL como o argumento de sinal para matar todos eles.
test_program_pid = fork();
if (test_program_pid) {
waitpid(test_program_pid, &status, 0);
if (kill(-test_program_pid, 0)) {
record_failue("some child processes were not terminated properly");
}
kill(-test_program_pid, SIGKILL);
} else {
setpgid(getpid(), getpid());
execve("/program/to/test", …);
}
Um método alternativo seria criar um arquivo temporário e abri-lo no programa que você está testando e em nenhum outro lugar. Se o programa chamar execve , verifique se o descritor de arquivo está aberto sem o sinalizador O_CLOEXEC (ou chame fcntl(fd, FD_CLOEXEC, 0) ). Esse método pressupõe que o programa não vá e feche os descritores de arquivo que ele não usa explicitamente. Você pode então executar fuser /temp/file para listar os processos que possuem este arquivo aberto e fuser -k /temp/file para eliminá-los. Uma variante dessa abordagem que funciona mesmo com programas que fecham descritores de arquivos que eles não usam, mas presumem que o programa não altera seu diretório atual, é criar um diretório temporário e mudar para esse diretório para executar o programa. / p>