Как избежать зависания read () в следующей ситуации? - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть некоторый код, который разветвляет стороннее приложение и перенаправляет его стандартный вывод в родительский процесс, примерно следующим образом (здесь для краткости нет обработки ошибок):

char* args[] = {"/path/to/3rd/party/binary", "with", "args", NULL};

int fds[2];
pipe2(fds, O_CLOEXEC);

pid_t pid = fork();
if (pid == 0)
{
    dup2(fds[1], STDOUT_FILENO);
    execvp(args[0], args);
    _exit(1);
}
else
{
    close(fds[1]);

    char buf[1024];
    int bytes_read;
    while ((bytes_read = read(fds[0], buf, sizeof buf - 1)) > 0)
    {
        buf[bytes_read] = '\0';
        printf("%s", buf);
    }

    close(fds[0]);
    waitpid(pid, NULL, 0);
}

У меня нет кода длястороннее приложение, это проприетарный бинарный файл.При запуске стороннего приложения в терминале с теми же аргументами, что и в приведенном выше коде, оно в конечном итоге завершается.Однако, когда разветвляется сторонний двоичный файл с использованием приведенного выше кода, он не завершается, а становится процессом-зомби, и приведенный выше код зависает при вызове read().

Сторонний двоичный файл, который являетсяразветвленный сам разветвляется на два демонических процесса (опять же, проприетарные двоичные файлы, которые я не контролирую), что, как мне кажется, вызывает здесь проблему.У разветвленных процессов-демонов будет копия дубликата файлового дескриптора, предотвращающая завершение read().Действительно, в случае замены вызова dup2() на:

dup3(fds[1], STDOUT_FILENO, O_CLOEXEC);

дочерний процесс завершается, но, конечно, перенаправление вывода на родительский процесс отсутствует.Кроме того, когда приведенный выше код изменен, чтобы не выполнять никакого перенаправления вывода на родительский объект по каналу, дочерний процесс завершается правильно.

Можно ли как-то предотвратить это зависание при вызове read() в этой ситуацииили мне нужно прибегнуть к какой-либо форме неблокирующего ввода-вывода?

Update;использование простого popen() страдает от той же проблемы.

(продолжение: read () зависает в процессе зомби )

1 Ответ

0 голосов
/ 30 ноября 2018

Вы должны специально игнорировать SIGCHLD.Это ваша обязанность пожинать зомби, но вы не можете сделать это, когда заблокированы в read.Если вы позвоните read после проглатывания SIGCHLD, вы останетесь в read навсегда.

...