2016-07-22 18 views
1

Thread::Suspendを使用して、リモートモジュールからスレッドを開始しています。 $subrotineコールの中には、30秒を超えるものがあります。Perlスレッドは中断/再開しません。

my $thr = threads->create(sub { 
    capture(EXIT_ANY, $^X, $pathToModule, $subroutine, %arguments) 
}); 
return $thr->tid(); 

私の問題は、作成したスレッドを中断/再開できないことです。

use IPC::System::Simple qw (capture $EXITVAL EXIT_ANY); 
use threads; 
use Thread::Suspend; 
use Try::Tiny; 

sub suspendThread { 
    my $msg; 
    my $threadNumber = shift; 

    foreach (threads->list()) { 
     if ($_->tid() == $threadNumber) { 
      if ($_->is_suspended() == 0) { 
       try { 
        # here the execution of the thread is not paused 
        threads->suspend($_); 
       } catch { 
        print "error: " . $! . "\n"; 
       }; 

       $msg = "Process $threadNumber paused"; 
      } else { 
       $msg = "Process $threadNumber has to be resumed\n"; 
      } 
     } 
    } 

    return $msg; 
} 

そして、これは私が動的にロードモジュールからのコードです:

sub run { 
    no strict 'refs'; 
    my $funcRef = shift; 
    my %paramsRef = @_; 
    print &$funcRef(%paramsRef); 
} 

run(@ARGV); 

私は問題はsubがトレッドに渡されるということであることを推測ここでは、コードのスレッドを中断するために実行されますコンストラクタはキャプチャを呼び出します(IPC::System::Simpleモジュールから)。私もmy $thr = threads->create(capture(EXIT_ANY, $^X, $pathToModule, $subroutine, %arguments));とスレッドを作成しようとしました。どのようにそれを解決するためのアイデア。

+0

あなたは何を達成しようとしていますか?なぜ単に使用しないのですか?スレッドを一時停止するセマフォーや他のIPC? – Sobrique

+0

「作成されたスレッドを中断/再開できない」ときはどうなりますか? _error_が印刷されていますか? '$ msg'とは何ですか? 'capture()'は少なくとも1つの子プロセスを作成するので、親プロセスのスレッドを子プロセスに保留することはどのような効果が期待されますか? – pilcrow

+0

ヒント: '$ _-> suspend()'は 'threads-> suspend($ _)'よりもはるかに奇妙に見えます。 – ikegami

答えて

2

これらはあなたが持っているスレッドです:

Parent process     Process launched by capture 
+---------------------+   +---------------------+ 
|      |   |      | 
| Main thread  |   | Main thread  | 
| +---------------+ |   | +---------------+ | 
| |    | |   | |    | | 
| | $t->suspend() | |   | |    | | 
| |    | |   | |    | | 
| +---------------+ |   | +---------------+ | 
|      |   |      | 
| Created thread  |   |      | 
| +---------------+ |   |      | 
| |    | |   |      | 
| | capture()  | |   |      | 
| |    | |   |      | 
| +---------------+ |   |      | 
|      |   |      | 
+---------------------+   +---------------------+ 

あなたが作成したスレッドが中断されていなかったと主張していますが、それが中断されたか否かを判断する実質的に方法がありません。結局、captureは何も印刷しないか、外部変数を変更しません。実際に、あなたはそれが中断されていないと信じる理由はありません。

これで、起動したプログラムをフリーズすることはできますが、そのプログラムやメインスレッドを一時停止することはできません。したがって、それは稼働し続けます[1]

外部プロセスを中断したい場合は、そのプロセスにSIGSTOPを送信することができます(また、SIGCONTを使用して再開することもできます)。そのためには、プロセスのPIDが必要です。 captureIPC::Runpumpループに置き換えることをお勧めします。それはあなたが実際にcaptureを実行中のスレッドを一時停止しなかったため、パイプがいっぱい得たのでSTDOUTへの書き込みしようとしたとき


  1. まあ、それは最終的にブロックします。
+0

私は 'IPC :: Run'のドキュメントを見ましたが、' capture 'を 'pump'に置き換える方法はまだ混乱しています。私は 'IPC :: Open2'から' capture2'を 'open2'に置き換えようとしましたが、置換えは役に立たないのです。 –

+0

' capture'を 'run'に置き換える方法は明らかでしょう。単に 'start' +' pump' + 'finish'です。 '$ h-> signal 'を使ってシグナルを送ることができます。 – ikegami

+0

'capture'を' run'に置き換えるのは明らかですが、 'run'を' start + pump + finish'シーケンスで置き換えるのは –

関連する問題