2012-06-29 52 views
2

我一直在嘗試實現一個在線裁判,但我被卡住了.. 我用fork創建一個子進程,然後從子進程中使用系統命令啓動我應該測試的程序。獲取子進程的執行結果C++

這是我用來測試分級機的程序。它處於一個無限循環中,但我只是評論這條線以使其工作。

#include <stdio.h> 
int main() { 
    int a, b; 
    scanf ("%d %d", &a, &b); 
    while (1); 
    printf ("%d\n", a + b); 

    return 0; 
} 

我編碼平地機至今

struct timeval start, end; 
    struct rlimit rl, default_memory, default_time; 
    getrlimit (RLIMIT_AS, &default_memory); 
    getrlimit (RLIMIT_CPU, &default_time); 

    pid_t pid = fork(); 

    gettimeofday (&start, NULL); 

    if (pid < 0) printf ("Error\n"); 
    else if (pid == 0) { // child process 
     if (memory_limit > 0) { 
      rl.rlim_cur = rl.rlim_max = memory_limit; 
      setrlimit (RLIMIT_AS, &rl); 
     } 

     if (time_limit > 0) { 
      rl.rlim_cur = rl.rlim_max = time_limit/1000 + 1; 
      setrlimit (RLIMIT_CPU, &rl); 
     } 


     ptrace (PTRACE_TRACEME, pid, NULL, NULL); 
     system ("./sum <in.txt> out.txt"); 

     setrlimit (RLIMIT_CPU, &default_time); 
     setrlimit (RLIMIT_AS, &default_memory); 
    } 
    else { // parent process 
     int *status; 


      // Is this ok? 
      // Because here http://linux.die.net/man/2/ptrace it says that 
      // PTRACE_GETSIGINFO is used to get information about the signal that 
      // caused the stop. And I'm interested If the program was killed because of 
      // rlimit (exceeding time or memory limit) or if it was something else. 
     ptrace (PTRACE_GETSIGINFO, pid, NULL, NULL); 
     if (wait (status) == -1) return 1; // waiting for the child process to finish 

     if (WIFSIGNALED (status)) { 
      int exit_signal = WTERMSIG (status); 
      printf ("Terminated with signal: %d.\n", exit_signal); 
      switch (exit_signal) { 
       case 0: 
        printf ("OK\n"); 
        break; 
       case SIGSEGV: // RLIMIT_AS -- SIGSEGV is sent, when the memory limit is exceeded 
        printf ("Memory Limit Exceeded\n"); 
        break; 
       case SIGXCPU: // RLIMIT_CPU -- when soft limit is reached SIGXCPU is sent 
       case SIGKILL: // when hard limit is reached SIGKILL is sent 
        printf ("Time Limit Exceeded\n"); 
        break; 
       default: // I didn't handle all the signals, so I made everything else a run time error 
        printf ("Run Time Error\n"); 
        break; 
      } 
     } 

     ptrace (PTRACE_KILL, pid, NULL, NULL); // Kill the process If it is not killed 

     gettimeofday (&end, NULL); // This is working fine 
     double time = (end.tv_sec - start.tv_sec) + 1e-6 * (end.tv_usec - start.tv_usec); 
     printf ("%lf\n", time); 
    } 

回答

2

你並不需要通過wait(2)使用ptrace的,你可以發送信號給孩子kill(2)並獲得退出狀態,如果因信號使用WTERMSIG退出。

問題可能是您正在使用system(),所以平地機實際上運行在第三個進程中,而不是在子進程中。我個人不會使用system()和類似的文件重定向,我會設置管道,然後在子中使用exec(),所以平地機實際上在子中運行。或者我只是使用我的pstreams庫。

+0

感謝您的回覆.. 好吧,我刪除了ptrace ..但是這並沒有改變enything ..我這裏的代碼只會在超過某個限制時殺死進程,但它不會告訴我哪個。這是最大的問題:( – user1410971

+0

看到我編輯的答案,孩子沒有得到信號,_grand_子進程,system()調用啓動的那個,孩子只是等待它完成 –

+1

..並且乾淨地退出,你可以試着讓孩子使用system()的返回值作爲退出狀態。 –

相關問題