1

一見単純な問題があります。一連のシステムコマンド(バッククォートを使用)を並行して実行する必要があります。

以下のコードは、私の問題を示す以外に意味のあるものをすべて取り除いています。

#!/usr/bin/perl -w 
use strict; 
use threads; 
use POSIX; 
my @threads = (); 
sub timeout { 
  print "TIMEOUT\n"; 
  foreach my $thread (@threads) { 
    $thread->kill("ALRM") if $thread->is_running(); 
  } 
} 

POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&timeout)); 
alarm(2); 
sub threadsub { 
  sub handletimeout { 
    print "KILL\n"; 
    threads->exit(1); 
  } 
  POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&handletimeout)); 
  # while(1) { sleep(1); } 
  return `sleep 10`; 
} 

for(my $i=0; $i < 10; $i++) { 
  push(@threads, thread->create(\&threadsub)); 
} 

foreach my $thread (@threads) { 
  my $res = $thread->join(); 
}

現在、問題は、スレッドがシステムコールでブロックされているときに、スレッドに送信されたALRMシグナルがキャッチされないことです。whileループのコメントを外すと、信号は意図したとおりにキャッチされます。システムコマンドでスタックしている場合でもスレッドをタイムアウトできるように、これを機能させるにはどうすればよいですか?

ありがとう、

キャスパー

4

1 に答える 1

0

男のスレッドから

   Unsafe signals
       Since Perl 5.8.0, signals have been made safer in Perl by postponing their handling until the interpreter is in a safe state.  See "Safe
       Signals" in perl58delta and "Deferred Signals (Safe Signals)" in perlipc for more details.

       Safe signals is the default behavior, and the old, immediate, unsafe signalling behavior is only in effect in the following situations:

       ?   Perl has been built with "PERL_OLD_SIGNALS" (see "perl -V").

       ?   The environment variable "PERL_SIGNALS" is set to "unsafe" (see "PERL_SIGNALS" in perlrun).

       ?   The module Perl::Unsafe::Signals is used.

       If unsafe signals is in effect, then signal handling is not thread-safe, and the "->kill()" signalling method cannot be used.

その効果は、perlが安全でない状態になるまで信号が延期されることを示しています。'unsafe-signals'に切り替えると、プログラムはメッセージで終了します。threads.plで安全なシグナルがないとスレッドにシグナルを送信できません安全でない信号がシステムで機能するかどうかを確認してください。それは動作しますが、安全ではありません。プロセスへの移行をお勧めします。以下のコードは、望ましい結果をもたらすはずです。

use strict;
use POSIX;

my $pid=fork();

sub timeout {
  print "TIMEOUT\n";
  kill SIGALRM,$pid;
}

if( $pid ) { ## parent
    alarm(2);
    POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&timeout));
    waitpid $pid,0;
} else { ## child
    sub handletimeout {
        print "SIGALRM child\n";
        exit(1);
    }
    POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&handletimeout));
    `sleep 10`;
    print "child normal exit";
}
于 2012-05-11T07:55:20.090 に答える