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>