что делать, если хвост не работает при чтении из канала

отличить стандартный вывод от стандартного вывода на конвейере

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

dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);

У меня вопрос, если каким-то образом tail выйдет из строя, что произойдет с каналом, из которого я читаю? Я получу что-нибудь на stderr? tail прекращает работу? или он может висеть там как defunct?


person hari    schedule 12.08.2011    source источник
comment
Поскольку они обмануты, я думаю, что ребенок, закрывающий один, также закроет другой, что приведет к сбою последующих записей в другой. Родитель получит конец файла. Но я не уверен на 100%.   -  person wberry    schedule 13.08.2011
comment
@wberry: на самом деле, закрытие - это единственное, что вы можете сделать с дублированным файловым дескриптором и не повлиять на другие его псевдонимы.   -  person hmakholm left over Monica    schedule 13.08.2011


Ответы (3)


вы не получаете EPIPE при чтении, только запись вернет EPIPE. Вы получите EOF, на что указывает чтение, возвращающее 0, и, поскольку вы читаете stderr, вы также получите сообщение об ошибке (до EOF).

Процесс станет зомби, и вы можете использовать wait/waitpid, чтобы получить статус выхода, который будет ненулевым, если произошла ошибка.

person Per Johansson    schedule 12.08.2011

Ядро отправит сигнал SIGPIPE другому процессу в канале, когда tail завершится. Действие по умолчанию для этого сигнала (если обработчик не установлен) — завершить процесс.

Если вы не хотите иметь дело с сигналами, вы можете игнорировать SIGPIPE в родительском (чтобы он не завершался, когда tail завершается), и вместо этого проверять, равно ли значение errno EPIPE после каждого read. Кроме того, вам нужно будет вызвать wait или waitpid из родителя, чтобы собрать дочерний элемент-зомби.

person Blagovest Buyukliev    schedule 12.08.2011
comment
Спасибо. Я просто хочу понять, почему SIGPIPE и ничего больше. - person hari; 13.08.2011
comment
Это старое, почти историческое соглашение Unix, но оно используется и сегодня. Тем не менее, вы можете игнорировать SIGPIPE и проверить, является ли errno EPIPE после read в родительском элементе. - person Blagovest Buyukliev; 13.08.2011
comment
SIGPIPE отправляется не при закрытии канала, а при попытке записи на другой конец. - person William Pursell; 14.08.2011

Если хвост завершается ошибкой, любое чтение на считываемом конце канала будет возвращать EOF. Если хвост дает сбой, он уже завершен, определение «сбой» состоит в том, что он завершился с ненулевым статусом выхода. Он останется в таблице процессов (т. е. «несуществующим») до тех пор, пока родитель не дождется его.

Но почему у вас есть хвост, использующий один и тот же канал для stderr и stdout? Почему бы просто не сделать две трубы? Кажется, что это устранило бы проблему различения двух выходных потоков.

person William Pursell    schedule 13.08.2011
comment
Спасибо, я полагаю, теперь мне даже не нужно читать stderr. Если tail не удастся, stdout получит EOF, правильно? И я так или иначе делаю wait для ребенка. Значит, будет убираться. Это звучит правильно? - person hari; 14.08.2011