Поскольку вы попросили предоставить ответ, я добавлю сюда дополнительную информацию, хотя я не уверен, что она полностью ответит на ваш вопрос.
Если предполагается, что целевой платформой является Linux, после уничтожения ipstream
в родительском процессе это фактически означает, что файловый дескриптор для связанного канала между родительским и дочерним процессом закрыт в родительском процессе. Как только дочерний процесс выполняет запись в канал после того, как родительский процесс закрыл его конец чтения канала, для дочернего процесса создается SIGPIPE
, что приводит к его завершению в случае, если дополнительные меры не предпринимаются.
Чтобы предотвратить это, один из вариантов - игнорировать SIGPIPE
у дочернего элемента. Теперь это приведет к ошибкам в дочернем процессе при записи в этот канал. Это будет зависеть от реализации дочернего процесса. Решением в вашем случае может быть игнорирование SIGPIPE
и принятие мер в дочернем процессе, если он больше не может успешно записывать данные, чтобы предотвратить много потерянных циклов ЦП.
Чтобы поэкспериментировать с этим нанижний уровень, вы можете использовать следующую программу. Он разветвляет дочерний процесс, который будет продолжать запись в некоторый вывод, пока это будет успешно выполнено. Родительский процесс закроет соответствующий канал, как только получит из него некоторые данные.
Поведение программы отличается в зависимости от того, как обрабатывается SIGPIPE
в дочернем процессе. В случае, если он игнорируется, write()
в дочернем процессе завершится ошибкой, и дочерний процесс завершит работу с ненулевым кодом завершения. Если SIGPIPE
не игнорируется, дочерний процесс завершается операционной системой. Родительский процесс расскажет вам, что произошло в дочернем процессе.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char** argv)
{
int pipe_fds[2];
if (pipe(pipe_fds) < 0) {
perror("pipe");
exit(1);
}
pid_t pid;
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
if (pid == 0)
{
close(pipe_fds[0]); /* close read-end in the child */
/* Uncomment the following line, and the child will terminate as soon
as the parent closes the read end of the pipe...This is here merely
for illustrative purposes, production code should use either
sigaction() or pthreads related signal functionality in case of a
multi-threaded program. */
/* signal(SIGPIPE, SIG_IGN); */
/* Child process, start writing to the write-end of the pipe. */
const char message[] = "Hello world!\n";
while (write(pipe_fds[1], message, strlen(message)) >= 0);
exit(1);
}
close(pipe_fds[1]);
char buf[256];
ssize_t count;
while ((count = read(pipe_fds[0], buf, sizeof(buf) - 1)) == 0);
if (count < 0) {
perror("read");
exit(1);
}
buf[count] = '\0';
printf("%s", buf);
/* Close read-end in the parent, this will trigger SIGPIPE in the child
once the child writes to the pipe. */
close(pipe_fds[0]);
int stat;
if (waitpid(pid, &stat, 0) < 0) {
perror("waitpid");
exit(1);
}
if (WIFSIGNALED(stat) && WTERMSIG(stat) == SIGPIPE) {
printf("\nChild terminated by SIGPIPE\n");
}
if (WIFEXITED(stat)) {
printf("\nChild exited with exit code %d\n", WEXITSTATUS(stat));
}
exit(0);
}