diff --git a/isolate.c b/isolate.c index e253a33..4770749 100644 --- a/isolate.c +++ b/isolate.c @@ -86,6 +86,17 @@ static void chowntree(char *path, uid_t uid, gid_t gid); static FILE *metafile; +static int +set_timer(int msec) +{ + struct itimerval new, old; + new.it_interval.tv_usec = 0; + new.it_interval.tv_sec = 0; + new.it_value.tv_usec = (msec%1000) * 1000; + new.it_value.tv_sec = msec/1000; + return setitimer(ITIMER_REAL, &new, &old); +} + static void meta_open(const char *name) { @@ -975,7 +986,6 @@ signal_alarm(int unused UNUSED) { /* Time limit checks are synchronous, so we only schedule them there. */ timer_tick = 1; - alarm(1); } static void @@ -1054,9 +1064,11 @@ get_run_time_ms(struct rusage *rus) static void check_timeout(void) { + int timer_time = -1000; if (wall_timeout) { int wall_ms = get_wall_time_ms(); + timer_time = wall_timeout - wall_ms; if (wall_ms > wall_timeout) err("TO: Time limit exceeded (wall clock)"); if (verbose > 1) @@ -1065,11 +1077,14 @@ check_timeout(void) if (timeout) { int ms = get_run_time_ms(NULL); + if (timeout - ms < timer_time && timeout >= ms) timer_time = timeout - ms; if (verbose > 1) fprintf(stderr, "[time check: %d msec]\n", ms); if (ms > timeout && ms > extra_timeout) err("TO: Time limit exceeded"); } + if (timer_tick && timer_time >= 0) + set_timer(timer_time + 100); } static void @@ -1092,7 +1107,7 @@ box_keeper(void) { sa.sa_handler = signal_alarm; sigaction(SIGALRM, &sa, NULL); - alarm(1); + set_timer((wall_timeout