Perl Carp 模块中的无限循环

4
我们有一些代码,捕获异常并记录消息,然后调用 Carp::longmess 来获取堆栈跟踪。因此,我们正在执行以下简化的操作:
eval { <some SOAP::Lite stuff> };
if( my $err = $@ )
{
    logwrite( "Caught Error: $err" );
}

logwrite函数本质上是:

sub logwrite($)
{
    my $msg = $_[0];
    my($pkg,$fil,$lin)=caller;
    my $timestamp = POSIX::strftime(...);
    print STDERR "$timestamp $fil/$lin $msg\n";
    print STDERR "$timestamp $fil/$lin Stack trace:\n" . Carp::longmess . "\n";
}

但是在日志中我看到:

20111030 Module.pm/42 Caught Error: at  line
Use of uninitialized value in caller at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 22.
Use of uninitialized value in string eq at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 91.
Use of uninitialized value in numeric lt (<) at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 200.
Use of uninitialized value in pattern match (m//) at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 55.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 55.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
...

那个来自 Carp/Heavy.pm 模块的警告序列一遍又一遍地重复,不断地吹出日志文件。所以我们最终将其杀掉。这些警告看起来像是由对 Carp::longmess 的调用触发的。这里另一个有趣的事情是 $@ 变量似乎只是 at。它是由 die 添加的 at,但没有实际的错误消息或行号。
有人以前见过这种情况吗?或者有任何关于 Carp 包正在发生什么的想法吗?这很罕见,但在过去的一个月左右已经发生了几次,而且我们每天都有数百个这样的任务在运行。

3
如果不知道您的调用堆栈是什么样子,我不确定如何重现您的错误。Carp肯定已经从堆栈顶部退出了。这可能是Carp中的一个错误或者是一个已损坏的堆栈。Carp可作为CPAN模块使用,请尝试升级?https://metacpan.org/release/Carp。另一个选项是尝试Perl 5.8.9。 - Schwern
POSIX可能在调用carp吗?你是否通过在longmess上设置断点并逐步执行来调试问题? - DVK
实际上,$@ 不包含 at。它包含一个空字符串,或者可能是未定义的。这并不那么不寻常。Carp 无法获取文件名或行号的能力则更加奇怪。 - ikegami
@Schwern。谢谢,这是有用的信息,可以继续搜索。不幸的是,升级并不是一个容易的选择,在我们的工作中,任何升级都需要经过QA周期等一系列步骤。但它使用了带有回调和基础调用LWP的SOAP::Lite,并且还有几个级别的eval。所以我猜在堆栈中可能会出现问题。不幸的是,它并不一致,就像我说的,数百次运行中只有一个。虽然对于这个数据集来说,是9个中的2个。 - Sodved
尝试本地安装升级版的Carp并查看是否修复了该错误(参见local::lib)。错误可能在Carp或Perl内部,您需要升级或打补丁。 - Schwern
@Schwern,这个问题很难复现,在过去30天的数千次运行中只发生了5次。因此,我们可能会在下一轮基础设施升级之前继续使用它。您是否想将您的评论整理成答案,然后我会接受它。 - Sodved
2个回答

1

你的代码在 perl v5.10.1 上运行良好,使用的是 Carp.pm 版本 1.11。

然而,请注意它所做的可能不是你期望的:由 longmess 产生的回溯将显示调用 logwrite 函数的位置,而不是实际错误发生在 eval 内部的位置。


0

我知道这并没有回答你的实际问题,但是...由于在这种情况下显然$msg eq 'at line ',也许你应该通过在print ... Carp::longmess ...语句的末尾添加unless $msg eq 'at line '来绕过这个问题?(我的意思是,除非有人提出一个真正的解决方案。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接