В приведенном ниже коде безопасно ли полагаться на сбой read () для обнаружения прекращения рождения ребенка?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
int pipefd[2];
pipefd[0] = 0;
pipefd[1] = 0;
pipe(pipefd);
pid_t pid = fork();
if (pid == 0)
{
// child
close(pipefd[0]); // close unused read end
while ((dup2(pipefd[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {} // send stdout to the pipe
while ((dup2(pipefd[1], STDERR_FILENO) == -1) && (errno == EINTR)) {} // send stderr to the pipe
close(pipefd[1]); // close unused write end
char *argv[3];
argv[0] = "worker-app";
argv[1] = NULL;
argv[2] = NULL;
execvp("./worker-app", argv);
printf("failed to execvp, errno %d\n", errno);
exit(EXIT_FAILURE);
}
else if (pid == -1)
{
}
else
{
// parent
close(pipefd[1]); // close the write end of the pipe in the parent
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
while (1) // <= here is it safe to rely on read below to break from this loop ?
{
ssize_t count = read(pipefd[0], buffer, sizeof(buffer)-1);
printf("pipe read return %d\n", (int)count);
if (count > 0)
{
printf("child: %s\n", buffer);
}
else if (count == 0)
{
printf("end read child pipe\n", buffer);
break;
}
else if (count == -1)
{
if (errno == EINTR)
{ continue;
}
printf("error read child pipe\n", buffer);
break;
}
}
close(pipefd[0]); // close read end, prevent descriptor leak
int waitStatus = 0;
waitpid(pid, &waitStatus, 0);
}
fprintf(stdout, "All work completed :-)\n");
return EXIT_SUCCESS;
}
Должен ли я что-то добавить в цикл while (1) для обнаружения дочернего завершения?Какой конкретный сценарий может произойти и сломать это приложение?
Некоторые мысли об улучшениях ниже.Однако я бы просто тратить циклы процессора?
Используйте команду kill со специальным аргументом 0, который не завершит процесс, а просто проверит, реагирует ли он: if (kill(pid, 0)) { break; /* child exited */ };
/ * Если sig равен 0, то сигнал не отправляется, нопроверка ошибок все еще выполняется;это можно использовать для проверки существования идентификатора процесса или идентификатора группы процессов.https://linux.die.net/man/2/kill * /
Используйте неблокирование waitpid в цикле while (1), чтобы проверить, вышел ли ребенок.
Используйте select (), чтобы проверить читаемость канала, чтобы предотвратить возможное зависание read ()?
Спасибо!