Perl coro分段错误



我有一个使用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 - $taskn";
            } => ($self, $task)
        );
        $h->{$coro} = $coro;
        $coro->on_destroy(sub {
            delete $h->{$coro};
            undef $coro;
        });
    }
    }
 }
AAA->new->main;

有时(如一天1次)由于分割错误而失败。

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

如果没有回溯(例如从coredump),很难说出原因,因为您没有提供关于它在哪里崩溃的信息。

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

使用重回调的代码(如使用AnyEvent或Coro的代码)创建循环数据结构在某种程度上更容易。

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

在coredump的反向跟踪中,您可能会看到调用Perl_croak或Perl_vcroak的实际错误。

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

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

最新更新