2011-09-15 29 views
3

私はThread::Poolモジュールをperlで使用して、いくつかのperlコードを並列化しています。このプロセスにはしばらく時間がかかり、ときどきコマンドラインからSIGINTを使用して強制終了します。そうすることで、予想通りにプログラムが突然終了します。これは、面倒な一時ファイルを残しているので、私はシグナルハンドラをインストールしたいと思います。私はこれをしました:スレッドperlとシグナルハンドラ

sub INT_Handler{ 
    #clean up code 
    exit(1); 
} 
$SIG{'INT'} = 'INT_handler'; 

スレッドプールを作成し、スレッドを開始する前に。今すぐSIGINTを送信すると、実行中のworker threadsが終了しますが、プールはすぐに次のジョブセットを処理する別のセットワーカーを起動し、実行を継続します。シグナルハンドラで終了する呼び出しがメインスレッドを終了しないのはなぜですか?プロセスの実行を停止するには何が必要ですか?

暴徒さんのコメントここ

**さらに編集**

に応じて編集私が書いた例があります。 0

use Thread::Pool; 

sub INT_handler{ 
    print "Handler\n"; 
    exit(1); 
} 

$SIG{'INT'}='INT_handler'; 

sub f{ 
    print "Started a thread " . rand(10000) . "\n"; 
    sleep(10); 
} 

my $pool; 
my $submit = \&f; 

if (0){ 
$pool = Thread::Pool->new({do=>'f', workers=>5}); 
    $submit = sub{ $pool->job; } 
} 

for (my $i = 0; $i < 100; $i++){ $submit->(); } 

$pool->shutdown if defined $pool; 

、私が期待した結果

h:57 Sep 15 16:15:19> perl tp.pl 
Started a thread 3224.83224635111 
Handler 

けどを参照してください1で、これは

h:57 Sep 15 16:14:56> perl tp.pl 
Started a thread 5034.63673711853 
Started a thread 9300.99967009486 
Started a thread 1394.45532885478 
Started a thread 3356.0428193687 
Started a thread 1424.4741558014 

などを発生し、ハンドラが入力されないと、プロセスが実行して続けます。 SIGINT以外のシグナルでプロセスを強制終了しなければなりませんでした。ハンドラがなければ、両方のケースは単にSIGINTを渡すと終了します。

+1

これは[ドキュメンテーション](http://search.cpan.org/perldoc?threads#BUGS_AND_LIMITATIONS)と競合しています:「シグナルはスクリプトのメインスレッド(スレッドID = 0)によって捕捉されます。 "ワーカースレッドでシグナルが捕捉されているようなコードを分離してポストすることはできますか? – mob

+0

@mob Ok。だから私は、信号が作業者によって捕らえられたと誤解しなければならない。私はシグナルハンドラでexitを明示的に呼び出すので、そうであると仮定しました。それでも、私が観察しているのは、死にかけているワーカースレッドと新しいワーカーが立ち上げられていることです。 –

答えて

4

これは決定的な答えではなくヒントですが、メインスレッドは信号ハンドラを実行するための決して「安全な」状態にはならないようです。おそらくそれとして(多分それは安全な信号でそれを実装するために正しい方向に導いてくれる -

PERL_SIGNALS=unsafe perl tp.pl

が安全と危険な信号の詳細については、perlipcを参照してください:それはあなたがPerlの危険な信号を有効にすると、作業を行いますすべきである)。


(暴徒による更新)建物はミハエルのオリジナルの洞察に、 Perl::Unsafe::Signalsでこの問題を回避するには、また、あなたが

use Perl::Unsafe::Signals; 
... 
UNSAFE_SIGNALS { 
    $pool->shutdown if defined $pool; 
}; 

を期待するように明確にそれはPerlの安全なシグナル伝達メカニズムについての何かがある仕事にハンドラを取得ハンドラへの途中で信号に干渉します。 UNSAFE_SIGNALS { ... }ブロックをThread::Pool::shutdownの内側に置くことでこれが修正されるのだろうかと思います。いずれにせよ、これについてはfile a bug reportでしょう。

+0

私の例の上に '$ ENV {PERL_SIGNALS} =" unsafe ";を追加しようとしましたが、私はまだ同じ問題を抱えていました。しかし、スクリプトを実行する前に環境変数を設定しても、動作しました。何故ですか? –

+1

この変数はおそらくperlがあなたのスクリプトの実行を開始したときにのみ評価されるので、スクリプトに設定するのは遅すぎます。 –

+1

私は、[PERL_SIGNALS]の内部設定が停止していると不満を寄せているスレッド[ここ](http://groups.google.com/group/perl.perl5.porters/browse_thread/thread/7cd25dcb2661ed67/3eeb441f1ce3e959?lnk=raot)が見つかりましたそれまで彼が喜んで使っていた間に5.14で働いていました。私は5.8.8を使用しています!それにもかかわらず、私はおそらく 'Perl :: Unsafe :: Signals'をインストールします。 –

関連する問題