2016-10-24 4 views
1

子を開始するプログラム(r.out)があり、その子に時間制限があります。タイムアウト後に完了していない場合、子プロセスを停止する方法

期限を過ぎてからr.outの実行を停止する方法を知りたいと思います。

私はLinux上でコードを実行しています。

これは私がこれまで持っているものです。

#include <unistd.h> 
#include <signal.h> 
#include <err.h> 
#include <stdio.h> 
#include <stdlib.h> 

#define TIME_LIMIT 1    //determine time limit 

void my_function();   //supposed to include the submitted code 
void alarm_handler(int); 



int main() 
{ 
    if (sigaction(SIGALRM, NULL, NULL) == -1) 
     err(1, NULL); 

    signal(SIGALRM, alarm_handler); // assigning an alarm handler for SIGALRM 

    alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT 

    system("./r.out"); //Running the file 

    alarm(0); 
    return 0; 
} 


void alarm_handler(int sig) 
{ 
    printf("%s" , "Time limit exceeded"); 
    //Here i want a code to stop the r.out file 
} 
+0

コードレビューサービスはありません。 – Olaf

+0

スレッドを使用できますか?もしそうなら、 'r.out'をスレッドで実行させ、' n'秒後にスレッドを終了させることができます。 –

+1

それに 'SIGKILL'を送ります。しかし、' fork/exec'を使ってより多くの制御をする方が良いでしょう。 –

答えて

0

子を殺すために、あなたはそのPIDを知っている必要があります。 systemの代わりにforkexecでプログラムを開始すると、それを得ることができます。

SIGALRMのシグナルハンドラに加えて、SIGCHLD(子プロセスが終了したときに受信)にも1を設定します。 alarmを呼び出してタイマーを設定したら、pauseに電話してください。この関数は、2つの信号のいずれかが得られたときに戻ります。

シグナルハンドラでは、グローバルフラグのみを設定してください。シグナルハンドラ内からprintfを呼び出すと、未定義の動作につながる可能性があります。

pauseが返された後、2つのフラグをそれぞれ確認してください。タイムアウトフラグが設定されている場合は、子をkillで終了することができます。

いずれの場合も、waitを呼び出して、子プロセスのpidを取得します。

#include <unistd.h> 
#include <signal.h> 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

#define TIME_LIMIT 1    //determine time limit 

void alarm_handler(int); 
void child_handler(int); 

int timeout = 0; 
int child_done = 0; 

int main() 
{ 
    pid_t pid = fork(); 
    if (pid == -1) { 
     perror("fork failed"); 
     exit(1); 
    } else if (pid == 0) { 
     // child process 
     execl("./r.out","r.out", NULL); 
     perror("exec failed"); 
     _exit(1); 
    } 

    // set up the signal handlers after forking so the child doesn't inherit them 

    signal(SIGALRM, alarm_handler); 
    signal(SIGCHLD, child_handler); 

    alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT 
    pause(); 

    if (timeout) { 
     printf("alarm triggered\n"); 
     int result = waitpid(pid, NULL, WNOHANG); 
     if (result == 0) { 
      // child still running, so kill it 
      printf("killing child\n"); 
      kill(pid, 9); 
      wait(NULL); 
     } else { 
      printf("alarm triggered, but child finished normally\n"); 
     } 
    } else if (child_done) { 
     printf("child finished normally\n"); 
     wait(NULL); 
    } 

    return 0; 
} 


void child_handler(int sig) 
{ 
    child_done = 1; 
} 

void alarm_handler(int sig) 
{ 
    timeout = 1; 
} 
+0

私はあなたがそれを過ぎていると思います。ダミーの 'SIGALRM'ハンドラをインストールし、' wait'を実行し、 'EINTR'で' -1'を返した場合は 'kill'を実行します。タイムアウト、 'pause'と' SIGCHLD'を処理する必要はありません。 – user58697

+0

@ user58697私がテストしていたマシンでは、タイマーの期限が切れたときに 'wait 'は' EINTR'で-1を返しません。このメソッドは、期限切れのケースと完全な時間のケースの両方ですべてが機能することを保証するために必要でした。 – dbush

+0

これは非常に奇妙です。 'wait'動作は完全に明確に定義されています。そのマシンは何だったのだろうか? – user58697

関連する問題