Разбитая труба больше не заканчивается программами? - PullRequest
5 голосов
/ 19 сентября 2008

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

$> do_something_intensive | less

, а затем выход из less , используемый для немедленного возврата вас к адаптивной оболочке SuSE8 или более ранних версий. когда я пытаюсь сделать это сегодня, do_something_intensive , очевидно, все еще работает, пока я не убью его вручную. Кажется, что-то изменилось (glib? Shell?), Что заставляет программу игнорировать «сломанные каналы» ...

У кого-нибудь из вас есть намеки на это? как восстановить прежнее поведение? почему он был изменен (или почему всегда существовала множественная семантика)?

edit : дальнейшие тесты (с использованием strace) показывают, что "SIGPIPE" генерируется , но программа не прерывается. Простой

#include <stdio.h>
int main() 
{
   while(1) printf("dumb test\n");
   exit(0);
}

будет продолжаться бесконечно

--- SIGPIPE (Broken pipe) @ 0 (0) ---
write(1, "dumb test\ndumb test\ndumb test\ndu"..., 1024) = -1 EPIPE (Broken pipe)

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

отредактируйте снова : похоже, что это проблема, специфичная для tcsh (bash обрабатывает ее правильно) и зависит от терминала (Eterm 0.9.4)

Ответы [ 3 ]

8 голосов
/ 19 сентября 2008

Что ж, если попытка записи в канал после того, как считыватель пропал, генерируется сигнал SIGPIPE. Приложение может перехватить этот сигнал, но если нет, процесс прекращается.

SIGPIPE не будет сгенерирован до тех пор, пока вызывающий процесс не попытается записать, поэтому, если выходных данных больше нет, он не будет сгенерирован.

2 голосов
/ 19 сентября 2008

Изменилось ли вообще "сделать что-нибудь интенсивное"?

Как сказал Дэниел, SIGPIPE - это не волшебный сигнал "ваша труба ушла", а скорее "хорошая попытка, вы больше не можете читать / писать эту трубу".

Если у вас есть контроль над «делать что-то интенсивное», вы можете изменить его, чтобы записывать некоторые выходные данные «индикатора прогресса» по мере его вращения. Это позволит своевременно поднять SIGPIPE.

0 голосов
/ 23 сентября 2008

Спасибо за советы, решение становится все ближе ...

В соответствии с man-страницей tcsh, «оболочки, не входящие в систему, наследуют поведение завершения от своих родителей. Другие сигналы имеют значения, которые оболочка унаследовала от своего родителя».

Что говорит о том, что мой терминал на самом деле является корнем проблемы ... если он игнорировал SIGPIPE, сама оболочка также проигнорирует SIGPIPE ...

edit: У меня есть окончательное подтверждение того, что проблема возникает только с Eterm + tcsh, и я обнаружил подозрительно отсутствующий сигнал (SIGPIPE, SIG_DFL) в исходном коде Eterm. Я думаю, что закрыть дело.

...