【发布时间】:2012-05-14 11:24:39
【问题描述】:
我正在尝试解决我在 perlipc 文档中看到的内容。
如果您正在写入管道,您还应该捕获 SIGPIPE。否则, 想想当你启动一个管道到一个命令时会发生什么 不存在:open() 很可能会成功(它只是 反映了 fork() 的成功),但是你的输出将 失败——壮观。 Perl 无法知道该命令是否有效 因为您的命令实际上是在一个单独的进程中运行 exec() 可能失败了。因此,虽然虚假命令的读者 仅返回文件的快速结束,伪造命令的编写者将触发 他们最好准备好处理的信号。考虑:
open(FH, "|bogus") or die "can't fork: $!";
print FH "bang\n" or die "can't write: $!";
close FH or die "can't close: $!";
直到收盘才会爆炸,它会爆炸 SIGPIPE。要抓住它,你可以使用这个:
$SIG{PIPE} = 'IGNORE';
open(FH, "|bogus") or die "can't fork: $!";
print FH "bang\n" or die "can't write: $!";
close FH or die "can't close: status=$?";
如果我没看错的话,它说第一个版本可能在最后关闭之前不会死。
但是,这在我的 OS X 机器上没有发生(Perl 版本 5.8.9 到 5.15.9)。无论我是否有 $SIG{PIPE} 行,它都会在 open 上以“无法分叉:没有这样的文件或目录”而爆炸。
我误会了什么?
【问题讨论】:
-
我认为
open已更改为更好地报告该案例,而perlipc未更新;您仍然可以获得记录在案的行为,但您需要使用更详细的open(..., '|-')机制。 -
geekosaur: 切换到
open my $fh, '|-', ''bogus" or die会出现同样的错误。 -
呃。我的意思是真的很长的路,你根本不指定命令,而是脚本本身
forks,你在孩子中运行exec。