1

スレッドからパッケージ変数にアクセスする際に問題があります。これは大きなプロジェクト用なので、コードの関連部分を抽出してみます。

オブジェクト指向部分にはスレッドモジュールとMooseを使用しています。

our $thread2;

around 'new' => sub {
  [...]
  threads->create( \&_thread1Func, $shared_self );
  if (!$thread2) {
    $thread2 = threads->create( \&_thread2Func, $shared_self );
    $thread2->detach();
  }
}

sub _thread1Func {
  $thread2->kill('SIGUSR1');
}

sub _thread2Func {
  $SIG{'USR1'} = sub { [...] };
  while (1) {
    sleep 5;
    [...]
  }
}

次のエラーが表示されます。

Thread N terminated abnormally: Can't call method "kill" on an undefined value at XXXX.pm line n.

線をn指しながら$thread2->kill('SIGUSR1');

$thread2 を宣言ourすると、パッケージ全体から見えるようになると考えていました。

何が起こっているかについて何か考えはありますか?

4

2 に答える 2

3

perldoc スレッドで述べたように:

Perl 5.8 以降、スレッド プログラミングは、スレッドごとに新しい Perl インタープリターを提供するインタープリター スレッドと呼ばれるモデルを使用して利用できるようになりました。デフォルトでは、データや状態情報がスレッド間で共有されることはありません。

our「現在のレキシカル スコープ内で使用するために、現在のパッケージ内の同じ名前のパッケージ変数にレキシカル エイリアスを作成します。」

これは、スレッド間で共有される変数を作成するという意味ではありません。そのためには、 threads::sharedが必要です。ただし、次の点に注意してください。

このモジュールは、次のデータ型の共有のみをサポートします: スカラーとスカラー参照、配列と配列参照、およびハッシュとハッシュ参照。

あなたのコードは私には面倒に見えます。なぜそのようなことをしているのかを説明していただければ、より具体的な支援を提供できるかもしれません。

以下は、あなたが望むものに近い何かをするかもしれません:

#!/usr/bin/env perl

use strict;
use warnings;

use threads;
use threads::shared;

my $thread2_tid :shared;

sub myfunc {
    threads->create(\&_thread1Func);
    if (!$thread2_tid) {
        my $thread2 = threads->create(\&_thread2Func);
        $thread2_tid = $thread2->tid;
    }
}

sub _thread1Func {
    while (1) {
        next unless defined $thread2_tid;
        last if $thread2_tid == -1;
        my $thread2 = threads->object($thread2_tid);
        $thread2->kill('SIGUSR1');
        sleep 1;
    }
}

sub _thread2Func {
    local $SIG{'USR1'} = sub { print "SIGUSR1 received\n" };
    local $| = 1;
    while (1) {
        sleep 1;
        print '.';
        if (5 < time - $^T) {
            $thread2_tid = -1;
            last;
        }
    }
}

myfunc();
$_->join for threads->list;
于 2013-08-20T17:14:50.343 に答える