2017-05-11 21 views
0

私のソースコードは、子プロセスがいくつかの他のプログラム(いくつかはC++)を呼び出してテストしていました。私はプリントをチェックアウトすると、10分後に、「タイムアウトなしの\と$ nowTimeで完了した実行のn」の部分はプリントアウトしますと、子プロセスがまだ実行されていることを タイムアウトを伴うPerlのkillプロセスは無視されました

#Other variables and functions 

my $MAX_TIME = 10;#testing 10 minutes 
my $timeRemaining = $MAX_TIME * 60; 
my $pid = fork(); 
if ($pid == 0) { 
    #child process 
    my $nowTime = localtime; 
    print "Run started at $nowTime\n"; 

    #This run() calls a for loop in perl, in each iteration there are several C++ programs 
    run(); 

    setpgrp(0,0); 
} 
elsif ($pid > 0){ 
    my $nowTime = localtime; 
    eval{ 
    local $SIG{ALRM} = sub { 
     kill -9, $pid; 
     print "Run completed at $nowTime\nJob time out for $MAX_TIME minutes\n"; 
     log(); 
     die "TIMEOUT!\n"; 
    }; 
    alarm $timeRemaining; 
    waitpid($pid, 0); 
    }; 
    print "Run completed at $nowTime with no timeout\n"; 
} 

は、私は気づきました。親プロセスの die "TIMEOUT!\n";部分は実行されません。 C++プログラムのために、perlプログラムが起動してもそれを強制終了できないのでしょうか?

+3

はヒント:負のシグナル番号を避けてください。混乱の原因となることがあります。 (例えば、シェルコマンド 'kill -9 $ pid'は、プロセスグループではなくプロセスにシグナルを送ります。)シェルやシステムコールのような負のPIDを使用します:' kill 9、 - $ pid; '、またはもっと良いことに、 'kill KILL => - $ pid;' – ikegami

+0

ありがとう。私は実際の 'run()'プログラムを 'print current_time() 'のようなダミーコードに置き換えた場合、\ n";睡眠1200;親プロセスが子プロセスを終了させようとしているにもかかわらず、print current_time()、 "\ n"; 'print current_time()の2行目\ n"; "は1200時(20分)に実行されます。 – jsh6303

+2

ヒント: 'setpgrp(0,0);'は 'setpgrp();'と書くことができます – ikegami

答えて

3

まず、$pidがプロセスグループではないため、killが失敗しています。

run(); 
setpgrp(0,0); 

は、第二

setpgrp(0,0); 
run(); 

あるべきタイムアウトがあります場合でも、あなたは

Run completed at $nowTime with no timeout 

を参照してください理由は、あなたが

print "Run completed at $nowTime with no timeout\n"; 
を実行することです3210

タイムアウトがあるかどうか。


第3に、子が刈り取られたときにalarmを無効にしないでください。

alarm(0); 

は第四に、あなたはそれをせずに現在の時刻を格納する$nowTimeを期待して追加します。


最後に、あなたがまだそれを殺す場合でも、あなたの子供を刈り取る必要があります。 (親はとにかくすぐに終了した場合[OK]を、これを省略することができる。)固定


use strict; 
use warnings; 

use POSIX qw(strftime); 

sub current_time { strftime("%Y-%m-%d %H:%M:%S", localtime) } 

sub run { 
    print("a\n"); 
    system('perl', '-e', 'sleep 3;'); 
    print("b\n"); 
    system('perl', '-e', 'sleep 3;'); 
    print("c\n"); 
} 

my $MAX_TIME = 5; 
my $pid = fork(); 
die($!) if !defined($pid); 
if ($pid) { 
    if (eval{ 
    local $SIG{ALRM} = sub { 
     kill KILL => -$pid; 
     die "TIMEOUT!\n"; 
    }; 
    alarm($MAX_TIME); 
    waitpid($pid, 0); 
    alarm(0); 
    return 1; 
    }) { 
    print "[".current_time()."] Run completed.\n"; 
    } else { 
    die([email protected]) if [email protected] ne "TIMEOUT!\n"; 
    print "[".current_time()."] Run timed out.\n"; 
    waitpid($pid, 0); 
    print "[".current_time()."] Child reaped.\n"; 
    } 
} else { 
    print "[".current_time()."] Run started.\n"; 
    setpgrp(0,0); 
    run(); 
} 

出力:

[2017-05-11 14:58:06] Run started. 
a 
b 
[2017-05-11 14:58:11] Run timed out. 
[2017-05-11 14:58:11] Child reaped. 
+0

ありがとうございます。私は 'run();'と 'setpgrp(0,0);'の順番を変えていることが分かりました。なぜ 'setpgrp(0,0)'を最初にやるべきか、もっと詳しく知ることができますか? – jsh6303

+0

あなたは決してそれに到達しないので – ikegami