如对这些问题的评论所述:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>Page cahced yet</h1>
<p>This is a paragraph.</p>
</body>
</html>
产生错误消息perl -e '$SIG{PIPE} = "IGNORE"; sleep(1); print "foo\n";' | echo -n
。
但是很奇怪
Unable to flush stdout: Broken pipe
不产生任何消息。
第二个命令为什么不产生消息?如何赶上SIGPIPE事件?
我真正需要的是(为了回答this question的实验)来捕获SIGPIPE,并在发生时将某些内容输出到日志文件中。
答案 0 :(得分:2)
在像示例中那样写入管道时,默认情况下会缓冲STDOUT。这意味着代码中的print "foo\n"
不会立即写入STDOUT,而是写入缓冲区,并且只有在缓冲区已满或作为程序清理的一部分时,才会刷新缓冲区(写入STDOUT)。使用strace
来查看您的程序实际上在做什么,这表明它首先将信号处理程序作为程序清理的一部分还原,然后写入STDOUT,从而导致SIGPIPE不再由您的子程序处理,因此导致杀死程序。
当确保立即完成输出而不是在程序清除时进行输出时,信号处理程序将被成功触发。这可以通过使用$|=1
使STDOUT无缓冲来实现:
$ perl -e \
'$|=1; $SIG{PIPE} = sub { print STDERR "XXX\n"; }; sleep(1); print "foo\n";' \
| echo -n
output: XXX
换句话说:如果激活,则信号处理程序将完美运行,并且它只是触发了您特定用途的人工制品。关于为什么它在退出时没有将信号处理程序从忽略(SIG_IGN
)重置为默认(SIG_DFL
)的问题,因此显示了我不知道的IGNORE相同的问题。