Re: поведение close на пайпе

From
Denis Shaposhnikov (2:550/5068)
To
Artem Chuprina
Date
2005-07-12T10:56:22Z
Area
RU.PERL
From: Denis Shaposhnikov <dsh@vlink.ru>

>>>>> "Artem" == Artem Chuprina <ran+news@ran.pp.ru> writes:

 DS> open(my $fh, "-|", "tail", "-F", "/some/file");

 DS> Теперь не понятно, как правильно $fh закрыть. Если просто
 DS> close($fh), то можно в результате оказаться заблокированным на
 DS> wait. Т.к. close ждет окончания процесса. А кто сказал, что он
 DS> захочет завершиться. Как же рекомендуется делать такие вещи?

 Artem> open тебе возвращает pid.  Сделай ему waitpid с WNOHANG.  Если
 Artem> закончился - зови close.  

Пробывал. Делаю свой обработчки CHLD, где в цикле waitpid с
WNOHANG. Теперь в цикле выполняю close($fh), а потом вышеописанный
open. По отладочному выводу вижу, что две итерации выполняются и мой
обработчки вызывается, а на третий упс, висим в wait статусе и мой
обработчки даже не вызвался. Висим именно на close. При этом, на том
конце пайпа либо никого нет уже, либо там висят в состоянии pipewr. Я
понимаю, что там заблокировались на записи, но мне этот пайп уже не
нужен. Я хочу закрыть его нафиг и что бы на том конце получили SIGPIPE
и успокоились.

 Artem> Но вообще как-то странно сформулирована задача.  Если не
 Artem> захочет завершиться, зачем close?  Если б ты сказал, что он
 Artem> может сделать это не сразу, я б еще поверил...

И не сразу в том числе. Проблема в том, что если происходит где-то
die, то управление передается вверх, за пределы видимости. И $fh тогда
уничтожается, а следовательно пытается закрыться. И не может. В итоге,
программа висит на этом close вечно.

 DS> close(STDERR) or warn "can't close STDERR: $!"; my $stderr_pid =
 DS> open(STDERR, "|-", @$logger); die "can't open pipe to
 DS> \"$logger_prog\": $!" unless defined
 Artem> $stderr_pid;
 DS> STDERR->autoflush(1);

 DS> close(STDOUT) or warn "can't close STDOUT: $!"; open( STDOUT,
 DS> ">&STDERR" ) or die "can't reopen STDOUT to STDERR: $!";
 DS> STDOUT->autoflush(1);

Вот по поводу этой конструкции. Сейчас опишу, как я понимаю из-за чего
виснет close. Пайп у нас уже запущен. Мы пытаемся закрыть STDERR и
close ждет завершения того конца pipe. Но он его никогда не дождется,
т.к. наш STDOUT туда же направлен и он не закрыть, следовательно для
программы на том конце пайпа eof на STDIN не наступит. Правильно я
понимаю?

 Artem> непустой - см. выше.  Тут, возможно, следует в какой-то
 Artem> ситуации сказать kill, чтобы он все-таки закрылся -
 Artem> файлхендлы-то вполне конкретные.

Ага, вот с kill понятнее. Но надо же это сделать нежно. Т.е. TERM
послать, потом подождать, потом KILL если не дождались. А как ждать,
wait'ом с взведенным alarm? Может есть какой-нибудь модуль, где это
уже реализовано?

 Artem> А вот на неявном flush с твоим STDOUT->autoflush(1) зависнуть
 Artem> у тебя есть все шансы.

Почему? Разве мне не вернется SIGPIPE?

-- 
DSS5-RIPE DSS-RIPN 2:550/5068@fidonet 2:550/5069@fidonet
mailto:dsh@vlink.ru http://neva.vlink.ru/~dsh/
--- Gnus/5.1007 (Gnus v5.10.7) XEmacs/21.4.17 (Jumbo Shrimp,
 berkeley-unix)
 * Origin: Solar system, Jupiter (2:550/5068@fidonet)
SEEN-BY: 450/208 452/25 100 454/9 455/15 461/33 74 106 640 464/34 465/204
SEEN-BY: 467/24 469/125 200 478/44 55 65 550/5004 5068 5127 4600/126 4614/9
SEEN-BY: 4623/56 4625/9 4626/100 4632/10 4635/99 1024 4641/444 4642/27 48
SEEN-BY: 4657/50 5001/50 5002/76 5002 5003/34 5010/53 146 5011/13 5015/4 28
SEEN-BY: 5015/214 5020/52 115 128 133 150 175 486 600 642 744 794 958 968 982
SEEN-BY: 5020/1100 1169 1212 1234 1626 1642 1653 1826 1829 1930 2044 2200 2345
SEEN-BY: 5020/2908 4400 4441 5021/2 5023/11 5024/1 73 5025/19 5030/69 195 382
SEEN-BY: 5030/436 611 920 1016 1039 1520 1688 5031/7 63 5032/11 20 5033/35
SEEN-BY: 5034/8 5035/38 63 5036/13 5037/21 36 5038/4 5040/33 47 5041/4 5045/7
SEEN-BY: 5045/42 5047/47 5049/6 157 5050/9 41 5051/35 5053/16 38 5054/1 8 9 35
SEEN-BY: 5054/36 37 45 50 66 67 81 85 5055/37 115 130 177 5056/16 5058/77
SEEN-BY: 5059/2 9 20 5060/90 5062/4 7 36 5063/51 5064/7 35 5070/26 66 5075/37
SEEN-BY: 5077/70 5079/49 5083/13 5090/23 105 5093/4 27 33 5096/18 5100/113
SEEN-BY: 6023/1 6033/2727 6055/4 6070/5
PATH: 550/5068 5020/52 5054/1 37