1

我有一个使用coro 6.06 版的 Perl 代码。

这是我的代码:

{
package AAA;
use AnyEvent::HTTP::LWP::UserAgent;
use Coro;
use Coro::AnyEvent; BEGIN { *CORE::GLOBAL::sleep = \&Coro::AnyEvent::sleep; };

sub new { return bless {} => shift };

sub main {
    my ($self) = @_;

    my $count = 1000;
    my $h = {};
    while (1) {
        while (keys %$h >= $count ) {
            sleep 1;
        }

        my $task = rand(1000);

        my $coro = async (
            sub {
                my ($self, $task) = @_;
                sleep( rand(1000) );
                print ": $self - $coro - $task\n";
            } => ($self, $task)
        );

        $h->{$coro} = $coro;
        $coro->on_destroy(sub {
            delete $h->{$coro};
            undef $coro;
        });
    }
    }
 }

AAA->new->main;

有时(例如一天中的 1 次)它会因分段错误错误而失败。

它可能是什么错误,我如何检测它?

4

1 回答 1

0

如果没有回溯(例如来自核心转储),很难说出原因,因为您没有提供有关崩溃位置的信息。

然而,C 库(例如 EV 或 Coro)的崩溃很常见,因为 perl 中存在一个长期存在的错误:当解释器退出时,它有时会破坏数据结构(通常是直接或间接属于循环数据结构的数据结构),即, perl 可能会释放仍然在别处引用的结构。

使用大量回调代码(例如使用 AnyEvent 或 Coro 的代码)创建循环数据结构稍微容易一些。

以下情况可能会导致这种情况:您的程序退出(例如,因为它抛出异常而没有捕获它,例如由于运行时错误)并且在程序退出期间,perl 破坏了一些导致段错误的 C 数据结构,这也意味着您实际上看不到错误消息。

在 coredump 的回溯中,您可能会看到对 Perl_croak 或 Perl_vcroak 的调用带有实际错误。

该 perl 错误的唯一解决方法是在程序退出时自己释放数据结构(例如,在退出之前自己取消定义全局变量)。如果您不能这样做(例如,因为您不知道它是 :),您可以自己捕获运行时错误(通过将代码包装到 eval 中),而不是正常退出程序,您可以打印错误并调用例如 POSIX::_exit 1。

使用 AnyEvent::Debug 会将所有观察者回调包装到 eval 中并为它们报告错误,因此这可能是一个开始。

于 2013-12-29T00:26:30.793 回答