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 日に 1 回のように) セグメンテーション違反エラーで失敗します。

どのようなバグで、どうすれば検出できますか?

4

1 に答える 1

0

バックトレース (コアダンプなど) がないと、クラッシュする場所に関する情報が提供されていないため、理由を説明するのは困難です。

ただし、C ライブラリ (EV や Coro など) でのクラッシュは、perl の長年のバグによりよく発生します: インタープリターが終了すると、データ構造 (通常は直接的または間接的に循環データ構造の一部であるデータ構造) が破損することがあります。 、perl はまだ他の場所で参照されている構造を解放する可能性があります。

循環データ構造の作成は、AnyEvent や Coro を使用するコードなど、コールバックを多用するコードを使用する方がいくらか簡単です。

次のシナリオがこれを引き起こす可能性があります: プログラムが終了し (たとえば、実行時エラーが原因でキャッチせずに例外をスローしたため)、プログラムの終了時に perl が一部の C データ構造を破壊して segfault を引き起こします。実際にエラーメッセージを見ることはありません。

コアダンプからのバックトレースで、Perl_croak または Perl_vcroak の呼び出しと実際のエラーを確認できる場合があります。

この perl バグの唯一の回避策は、プログラムの終了時に自分でデータ構造を解放することです (たとえば、終了する前に自分でグローバル変数を undef することによって)。それができない場合 (たとえば、手がかりがないため :)、(コードを eval にラップすることによって) 自分で実行時エラーをキャッチでき、通常どおりプログラムを終了する代わりに、エラーを出力して呼び出すことができます。たとえば、POSIX::_exit 1 です。

AnyEvent::Debug を使用すると、すべてのウォッチャー コールバックが eval にラップされ、それらのエラーが報告されるため、それが出発点になる可能性があります。

于 2013-12-29T00:26:30.793 に答える