Perl升级后的奇怪错误:无法刷新stdout

问题描述 投票:1回答:3

升级到Perl 5.24.4后,我们在日志中反复出现此错误(不指向文件名和行号):

无法冲洗标准输出:管道损坏

我们不知道导致此错误的原因。

有什么建议如何理解错误的原因?

perl runtime-error warnings
3个回答
5
投票

该错误来自perl.c, line 595

        PerlIO_printf(PerlIO_stderr(), "Unable to flush stdout: %s",
                      Strerror(errno));

这行是perl_destruct的一部分,在程序结束时调用它来关闭perl解释器。

作为全局关闭过程的一部分,所有仍然打开的文件句柄都被刷新(即写出所有缓冲的输出)。上面的评论说:

 /* Need to flush since END blocks can produce output */
 /* flush stdout separately, since we can identify it */

错误消息未在perldoc perldiag中列出,这可能是文档错误。它可能被忽视,因为它不是真正的warndie电话,它实际上只是print STDERR $message。它与文件名或行号无关,因为它只在程序停止运行后发生(即在调用exit之后或因为执行从主脚本结束时掉落)。


2
投票

这是非常一般的建议,但是

use Carp::Always;

在脚本的顶部,或运行

perl -MCarp::Always the_script.pl arg1 arg2 ...

将使Perl产生每个警告和错误的堆栈跟踪。


2
投票

Broken pipe是与系统错误EPIPE相关联的错误字符串。写入封闭管道时会收到此错误。通常写入封闭的管道会导致进程被SIGPIPE杀死,因此这意味着SIGPIPE的行为已从其默认值更改。

$ perl -e'
   $SIG{PIPE} = "IGNORE";
   print "foo\n"
      or die("Can\x27t write to STDOUT: $!\n");
   sleep(2);
   close(STDOUT)
      or die("Unable to flush STDOUT: $!\n");
' | perl -e'sleep(1)'
Unable to flush STDOUT: Broken pipe

作为melpomene discovered,如果您写入END块中的损坏管道,则会自动输出错误。

$ perl -e'
   $SIG{PIPE} = "IGNORE";
   sleep(2);
   END { print "foo\n"; }
' | perl -e'sleep(1)'
Unable to flush stdout: Broken pipe

这不一定是个问题,尽管这可能是一个过程过早退出的迹象。

© www.soinside.com 2019 - 2024. All rights reserved.