From 9476dd8c6041193efdbe572275caff6dfaa5dbf7 Mon Sep 17 00:00:00 2001 From: Claudiu Gheorghe Date: Fri, 9 Apr 2010 18:16:18 +0300 Subject: [PATCH] Larger granularity on setting the time limit: microseconds --- testing/pa/dummy/c.timeout | 2 +- testing/pa/dummy/java.timeout | 2 +- testing/pa/tracker.c | 83 +++++++++++++++++++++-------------- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/testing/pa/dummy/c.timeout b/testing/pa/dummy/c.timeout index 0cfbf08..95e3ba8 100644 --- a/testing/pa/dummy/c.timeout +++ b/testing/pa/dummy/c.timeout @@ -1 +1 @@ -2 +2.5 diff --git a/testing/pa/dummy/java.timeout b/testing/pa/dummy/java.timeout index 0cfbf08..95e3ba8 100644 --- a/testing/pa/dummy/java.timeout +++ b/testing/pa/dummy/java.timeout @@ -1 +1 @@ -2 +2.5 diff --git a/testing/pa/tracker.c b/testing/pa/tracker.c index 72b30af..0327af9 100644 --- a/testing/pa/tracker.c +++ b/testing/pa/tracker.c @@ -7,7 +7,7 @@ * limit on CPU execution time * * Arguments: - * argv[1]: timeout - currently in seconds + * argv[1]: timeout - float value in seconds * argv[2]: input filename * argv[3]: output filename */ @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,10 @@ #define MAKEFILE "Makefile" #define MAKEFILE_TARGET "run" -void setup_job(int timeout, char *in, char *out) { +#define UERR 1000 +#define UFACT 1000000 + +int setup_job(int timeout, char *in, char *out) { struct rlimit limit; /* set the processor time limit */ @@ -37,26 +41,27 @@ void setup_job(int timeout, char *in, char *out) { /* redirect input and output */ int fd_in = open(in, O_RDONLY); if (fd_in < 0) { - fprintf(stderr, "Error opening job input file `%s`: %s\n", in, strerror(errno)); - exit(EXIT_FAILURE); + fprintf(stderr, "Error opening job input file `%s`: %s\n", in, strerror(errno)); + return 1; } if (dup2(fd_in, STDIN_FILENO) < 0) { - fprintf(stderr, "Error duplicating input fd: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + fprintf(stderr, "Error duplicating input fd: %s\n", strerror(errno)); + return 1; } int fd_out = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd_out < 0) { - fprintf(stderr, "Error opening job output file `%s`: %s\n", out, strerror(errno)); - exit(EXIT_FAILURE); + fprintf(stderr, "Error opening job output file `%s`: %s\n", out, strerror(errno)); + return 1; } if (dup2(fd_out, STDOUT_FILENO) < 0) { - fprintf(stderr, "Error duplicating output fd: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + fprintf(stderr, "Error duplicating output fd: %s\n", strerror(errno)); + return 1; } - + + return 0; } int main(int argc, char *argv[], char *const envp[]) { @@ -65,34 +70,48 @@ int main(int argc, char *argv[], char *const envp[]) { char *childargv[] = {"make", "-s", "--no-print-directory", "-f", MAKEFILE, MAKEFILE_TARGET, NULL}; if (argc != 4) { - fprintf(stderr, "Usage: ./tracker \n"); - exit(EXIT_FAILURE); + fprintf(stderr, "Usage: ./tracker \n"); + exit(EXIT_FAILURE); } - int timeout = atoi(argv[1]); + float ftimeout; + int timeout; + sscanf(argv[1], "%f", &ftimeout); + timeout = (int)ceil(ftimeout); child_pid = fork(); if (-1 == child_pid) { - fprintf(stderr, "Error in fork(): %s\n", strerror(errno)); - exit(EXIT_FAILURE); + fprintf(stderr, "Error in fork(): %s\n", strerror(errno)); + exit(EXIT_FAILURE); } else if (0 == child_pid) { - setup_job(timeout, argv[2], argv[3]); - execve("/usr/bin/make", childargv, envp); - /* should not be here */ - fprintf(stderr, "Error in execve(): %s\n", strerror(errno)); - exit(EXIT_FAILURE); + if (setup_job(timeout, argv[2], argv[3])) { + exit(EXIT_FAILURE); + } + execve("/usr/bin/make", childargv, envp); + /* should not be here */ + fprintf(stderr, "Error in execve(): %s\n", strerror(errno)); + exit(EXIT_FAILURE); } else { - struct rusage accounting; - w = wait4(child_pid, &status, 0, &accounting); - if (WEXITSTATUS(status)) { - /* we got an error */ - return WEXITSTATUS(status); - } else { - /* print some stats */ - fprintf(stdout, "time: %d.%d seconds\n", - (int)accounting.ru_utime.tv_sec + (int)accounting.ru_stime.tv_sec, - (int)accounting.ru_utime.tv_usec + (int)accounting.ru_stime.tv_usec); - } + struct rusage accounting; + w = wait4(child_pid, &status, 0, &accounting); + if (WEXITSTATUS(status)) { + /* we got an error */ + return WEXITSTATUS(status); + } else { + /* print some stats */ + int seconds = (int)accounting.ru_utime.tv_sec + (int)accounting.ru_stime.tv_sec; + int useconds = (int)accounting.ru_utime.tv_usec + (int)accounting.ru_stime.tv_usec; + if (seconds == timeout - 1) { + int utimeout = (int)((ftimeout - (float)(timeout - 1)) * UFACT); + if (useconds - utimeout > UERR) { + fprintf(stderr, "CPU time limit exceeded\n"); + return 1; + } + } + /* success */ + float ftime = (float)seconds + (float)useconds / UFACT; + fprintf(stdout, "time: %f seconds\n", ftime); + } } return 0;