int main (int argc, char* argv[]) { int cmd_start_index; int i; pid_t pid, hardlimit_monitor; init_default_limits (); cmd_start_index = parse_args (argc, argv); /* be safe on the timehard! */ if (limit_timehard < 1 + (int) ceil (limit_time)) limit_timehard = 1 + (int) ceil (limit_time); /* close inherited file descriptors. Is there a better way? */ for (i = 3; i < (1<<16); i++) close (i); pid = fork(); if (pid==0) { return subprocess (argc - cmd_start_index, argv + cmd_start_index); } hardlimit_monitor = fork (); if (hardlimit_monitor == 0) { sleep (6*limit_timehard); /* if I reached here, then the main process is still running, * upto some race condition possibilitiy */ //fprintf (stderr, "Severe hardlimit (%d) reached. Possibly \ malicious, or overloaded system.\n", 6*limit_timehard); kill (pid, 9); return 0; } int status; struct rusage usage ; /* * Correctness: Pid dies on its own or, hardlimit_monitor process * kills it. In both cases, this works, except perhaps the Pid * process can be called for kill twice. */ wait4(pid,&status, 0, &usage); //Wait for child to terminate kill (hardlimit_monitor, 9); waitpid (hardlimit_monitor, NULL, 0); // lets output the limits. fflush(stderr) ; /* ordering of output of child and parent should be right */ double usertime = (float) (usage.ru_utime.tv_sec) + ((float) usage.ru_utime.tv_usec)/1000000 ; //fprintf(stderr, "Usertime: %lf\n", usertime);
int main (int argc, char* argv[]) { int cmd_start_index; int i; pid_t pid, hardlimit_monitor; init_default_limits (); cmd_start_index = parse_args (argc, argv); if (limit_timehard < 1 + (int) (limit_time)) limit_timehard = 1 + (int) (limit_time); /* close inherited file descriptors. Is there a better way? */ for (i = 3; i < (1<<16); i++) close (i); pid = fork(); if (pid==0) { return subprocess (argc - cmd_start_index, argv + cmd_start_index); } hardlimit_monitor = fork (); if (hardlimit_monitor == 0) { sleep (6*limit_timehard); kill (pid, 9); return 0; } int status; struct rusage usage ; wait4(pid,&status, 0, &usage); //Wait for child to terminate kill (hardlimit_monitor, 9); waitpid (hardlimit_monitor, NULL, 0); fflush(stderr) ; /* ordering of output of child and parent should be right */ double usertime = (float) (usage.ru_utime.tv_sec) + ((float) usage.ru_utime.tv_usec)/1000000 ; double systime = (float) (usage.ru_stime.tv_sec) + ((float)usage.ru_stime.tv_usec)/1000000 ; if(WIFSIGNALED(status)) { int signal = WTERMSIG(status); #define die(s) { fprintf(stderr,s) ; exit(0) ; } if(signal==SIGXCPU) die("TLE Time limit exceeded (H)\n"); if(signal==SIGFPE) die("FPE Floating point exception\n"); if(signal==SIGILL) die("ILL Illegal instruction\n"); if(signal==SIGSEGV) die("SEG Segmentation fault\n"); if(signal==SIGABRT) die("ABRT Aborted (got SIGABRT)\n"); if(signal==SIGBUS) die("BUS Bus error (bad memory access)\n"); if(signal==SIGSYS) die("SYS Invalid system call\n"); if(signal==SIGXFSZ) die("XFSZ Output file too large\n"); if(signal==SIGKILL) die("KILL Your program was killed (probably because of excessive memory usage)\n"); die("UNK Unknown error, possibly your program does not return 0, or maybe its some fault of ours!"); } if (usertime + systime > limit_time) die("TLE Time Limit exceeded\n") ; if (!WIFEXITED(status)) { fprintf (stderr,"EXIT Program exited abnormally. This could be due to excessive memory usage, or any runtime error that is impossible to determine.\n"); exit (0); } if (WEXITSTATUS(status) != 0) { fprintf (stderr,"EXIT Program did not return 0\n", WEXITSTATUS(status)); exit (0); } return 0; }