6

我试图通过我在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)。open无论我在那里是否有 $SIG{PIPE} 行,它都会以“无法分叉:没有这样的文件或目录”而爆炸。

我有什么误解?

4

2 回答 2

3

这是在 5.6 的开发过程中实现的更改,以便 system() 可以检测到它何时无法分叉/执行子

https://github.com/mirrors/perl/commit/d5a9bfb0fc8643b1208bad4f15e3c88ef46b4160

它也记录在http://search.cpan.org/dist/perl/pod/perlpentut.pod#Pipe_Opens

它本身指向 perlipc,但 perlipc 似乎确实缺少这个

于 2012-05-05T00:56:25.793 回答
0

我的 Perl v5.14.2、Ubuntu 12.04 上的输出相同:

$ perl
   open(FH, "|bogus")  or die "can't fork: $!";
   print FH "bang\n"   or die "can't write: $!";
   close FH            or die "can't close: $!";
can't fork: No such file or directory at - line 1.

这个错误很奇怪,因为它与分叉无关——他们一定添加了一些前瞻猜测,看看它是否可以执行bogus。(这充其量是一种竞争条件,但在常见情况下可能会提供明显更好的错误处理;并且只会在竞争失败时与旧行为一样不方便。)

于 2012-05-04T22:33:57.687 回答