Description:
[grader] added fractional timelimit git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@191 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r51:3618759afb50 - - 6 files changed: 66 inserted, 57 deleted

@@ -0,0 +1,38
1 + #include <stdio.h>
2 + #include <stdlib.h>
3 + #include <unistd.h>
4 + #include <sys/time.h>
5 + #include <time.h>
6 + #include <sys/resource.h>
7 +
8 + // run it for 1.5 s
9 +
10 + int main()
11 + {
12 + int a,b;
13 +
14 + int c=0;
15 +
16 + scanf("%d %d",&a,&b);
17 + printf("%d\n",a+b);
18 +
19 + struct rusage ru;
20 +
21 + while(1) {
22 + c++;
23 + b+=c;
24 + while(c<100000) {
25 + c++;
26 + b+=c;
27 + }
28 + getrusage(RUSAGE_SELF,&ru);
29 + double rtime = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
30 + rtime += (double)ru.ru_utime.tv_usec / 1000000.0;
31 + rtime += (double)ru.ru_stime.tv_usec / 1000000.0;
32 + if(rtime > 0.5)
33 + break;
34 + }
35 + printf("%d\n",b);
36 + exit(0);
37 + }
38 +
@@ -146,39 +146,44
146 146 while true
147 147
148 148 if check_stopfile # created by calling grader stop
149 149 clear_stopfile
150 150 log "stopped (with stop file)"
151 151 break
152 152 end
153 153
154 154 if grader_mode=="queue"
155 155 task = runner.grade_oldest_task
156 156 else
157 157 task = runner.grade_oldest_test_request
158 158 end
159 159 if task==nil
160 160 sleep(1)
161 161 end
162 162 end
163 163
164 164 when "prob"
165 165 engine = Grader::Engine.new
166 166 runner = Grader::Runner.new(engine, grader_proc)
167 167
168 168 grader_proc.report_active if grader_proc!=nil
169 169
170 - prob = Problem.find_by_name(ARGV[2])
171 - if prob==nil
172 - puts "cannot find problem: #{ARGV[2]}"
173 - else
174 - runner.grade_problem(prob)
170 + ARGV.shift
171 + ARGV.shift
172 +
173 + ARGV.each do |prob_name|
174 + prob = Problem.find_by_name(prob_name)
175 + if prob==nil
176 + puts "cannot find problem: #{prob_name}"
177 + else
178 + runner.grade_problem(prob)
179 + end
175 180 end
176 181
177 182 else
178 183 display_manual
179 184 exit(0)
180 185 end
181 186
182 187 # report inactive
183 188 grader_proc.report_inactive if grader_proc!=nil
184 189
@@ -8,49 +8,49
8 8 //#define _GNU_SOURCE
9 9
10 10 #include <errno.h>
11 11 #include <stdio.h>
12 12 #include <fcntl.h>
13 13 #include <stdlib.h>
14 14 #include <string.h>
15 15 #include <stdarg.h>
16 16 #include <unistd.h>
17 17 #include <getopt.h>
18 18 #include <time.h>
19 19 #include <sys/wait.h>
20 20 #include <sys/user.h>
21 21 #include <sys/time.h>
22 22 #include <sys/ptrace.h>
23 23 #include <sys/signal.h>
24 24 #include <sys/sysinfo.h>
25 25 #include <sys/syscall.h>
26 26 #include <sys/resource.h>
27 27
28 28 #define NONRET __attribute__((noreturn))
29 29 #define UNUSED __attribute__((unused))
30 30
31 31 static int filter_syscalls; /* 0=off, 1=liberal, 2=totalitarian */
32 - static int timeout;
32 + static double timeout;
33 33 static int pass_environ;
34 34 static int use_wall_clock;
35 35 static int file_access;
36 36 static int verbose;
37 37 static int memory_limit;
38 38 static int allow_times;
39 39 static char *redir_stdin, *redir_stdout;
40 40 static char *set_cwd;
41 41
42 42 static pid_t box_pid;
43 43 static int is_ptraced;
44 44 static volatile int timer_tick;
45 45 static time_t start_time;
46 46 static int ticks_per_sec;
47 47 static int page_size;
48 48
49 49 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ > 0
50 50 /* glibc 2.1 or newer -> has lseek64 */
51 51 #define long_seek(f,o,w) lseek64(f,o,w)
52 52 #else
53 53 /* Touching clandestine places in glibc */
54 54 extern loff_t llseek(int fd, loff_t pos, int whence);
55 55 #define long_seek(f,o,w) llseek(f,o,w)
56 56 #endif
@@ -306,90 +306,90
306 306 return 0;
307 307 }
308 308 }
309 309
310 310 static void
311 311 signal_alarm(int unused UNUSED)
312 312 {
313 313 /* Time limit checks are synchronous, so we only schedule them there. */
314 314 timer_tick = 1;
315 315
316 316 //NOTE: do not use alarm, changed to setitimer for precision
317 317 // alarm(1);
318 318 }
319 319
320 320 static void
321 321 signal_int(int unused UNUSED)
322 322 {
323 323 /* Interrupts are fatal, so no synchronization requirements. */
324 324 die("Interrupted.");
325 325 }
326 326
327 327 static void
328 328 check_timeout(void)
329 329 {
330 - int sec;
330 + double sec;
331 331
332 332 if (use_wall_clock)
333 - sec = time(NULL) - start_time;
333 + sec = (double)(time(NULL) - start_time);
334 334 else
335 335 {
336 336 char buf[4096], *x;
337 337 int c, utime, stime;
338 338 static int proc_status_fd;
339 339 if (!proc_status_fd)
340 340 {
341 341 sprintf(buf, "/proc/%d/stat", (int) box_pid);
342 342 proc_status_fd = open(buf, O_RDONLY);
343 343 if (proc_status_fd < 0)
344 344 die("open(%s): %m", buf);
345 345 }
346 346 lseek(proc_status_fd, 0, SEEK_SET);
347 347 if ((c = read(proc_status_fd, buf, sizeof(buf)-1)) < 0)
348 348 die("read on /proc/$pid/stat: %m");
349 349 if (c >= (int) sizeof(buf) - 1)
350 350 die("/proc/$pid/stat too long");
351 351 buf[c] = 0;
352 352 x = buf;
353 353 while (*x && *x != ' ')
354 354 x++;
355 355 while (*x == ' ')
356 356 x++;
357 357 if (*x++ != '(')
358 358 die("proc syntax error 1");
359 359 while (*x && (*x != ')' || x[1] != ' '))
360 360 x++;
361 361 while (*x == ')' || *x == ' ')
362 362 x++;
363 363 if (sscanf(x, "%*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d", &utime, &stime) != 2)
364 364 die("proc syntax error 2");
365 365 //printf("%s - %d\n",x,ticks_per_sec);
366 - sec = (utime + stime + ticks_per_sec-1)/ticks_per_sec;
366 + sec = ((double)(utime + stime))/(double)ticks_per_sec;
367 367 }
368 368 if (verbose > 1)
369 369 fprintf(stderr, "[timecheck: %d seconds]\n", sec);
370 370 if (sec > timeout) {
371 - die("Time limit exceeded.");
371 + die("Time limit exceeded.",sec,timeout);
372 372 }
373 373 }
374 374
375 375 static void
376 376 check_memory_usage()
377 377 {
378 378 char proc_fname[100];
379 379 sprintf(proc_fname,"/proc/%d/statm",box_pid);
380 380 //printf("proc fname: %s\n",proc_fname);
381 381 FILE *fp = fopen(proc_fname,"r");
382 382 if(fp!=NULL) {
383 383 char line[1000];
384 384 fgets(line,999,fp);
385 385 //printf("%s\n",line);
386 386 int m;
387 387
388 388 if(sscanf(line,"%d",&m)==1) {
389 389 m = (m*page_size+1023)/1024;
390 390 if(m>max_mem_used)
391 391 max_mem_used = m;
392 392 }
393 393
394 394 fclose(fp);
395 395 }
@@ -445,49 +445,52
445 445 check_timeout();
446 446 check_memory_usage();
447 447 timer_tick = 0;
448 448 }
449 449 p = wait4(box_pid, &stat, WUNTRACED, &rus);
450 450
451 451 if (p < 0)
452 452 {
453 453 if (errno == EINTR)
454 454 continue;
455 455 die("wait4: %m");
456 456 }
457 457 if (p != box_pid)
458 458 die("wait4: unknown pid %d exited!", p);
459 459 if (WIFEXITED(stat))
460 460 {
461 461 struct timeval total;
462 462 int wall;
463 463 wall = time(NULL) - start_time;
464 464 timeradd(&rus.ru_utime, &rus.ru_stime, &total);
465 465
466 466 box_pid = 0;
467 467 if (WEXITSTATUS(stat))
468 468 fprintf(stderr,"Exited with error status %d.\n", WEXITSTATUS(stat));
469 - else if ((use_wall_clock ? wall : total.tv_sec) > timeout)
469 + else if ((use_wall_clock ?
470 + wall :
471 + (double) total.tv_sec +
472 + ((double) total.tv_usec/1000000.0)) > timeout)
470 473 fprintf(stderr,"Time limit exceeded.\n");
471 474 else
472 475 // report OK and statistics
473 476 fprintf(stderr,"OK\n");
474 477
475 478 print_running_stat((double) wall,
476 479 (double) rus.ru_utime.tv_sec +
477 480 ((double) rus.ru_utime.tv_usec/1000000.0),
478 481 (double) rus.ru_stime.tv_sec +
479 482 ((double) rus.ru_stime.tv_usec/1000000.0),
480 483 max_mem_used);
481 484 /*
482 485 (%.4lf sec real (%d), %d sec wall, %d syscalls, %d kb)\n",
483 486 (double) total.tv_sec + ((double)total.tv_usec / 1000000.0),
484 487 (int) total.tv_usec,
485 488 wall,
486 489 syscall_count,
487 490 max_mem_used);
488 491 */
489 492 exit(0);
490 493 }
491 494 if (WIFSIGNALED(stat))
492 495 {
493 496 box_pid = 0;
@@ -625,49 +628,49
625 628 switch (c)
626 629 {
627 630 case 'a':
628 631 file_access = atol(optarg);
629 632 break;
630 633 case 'c':
631 634 set_cwd = optarg;
632 635 break;
633 636 case 'e':
634 637 pass_environ = 1;
635 638 break;
636 639 case 'f':
637 640 filter_syscalls++;
638 641 break;
639 642 case 'i':
640 643 redir_stdin = optarg;
641 644 break;
642 645 case 'm':
643 646 memory_limit = atol(optarg);
644 647 break;
645 648 case 'o':
646 649 redir_stdout = optarg;
647 650 break;
648 651 case 't':
649 - timeout = atol(optarg);
652 + timeout = atof(optarg);
650 653 break;
651 654 case 'T':
652 655 allow_times++;
653 656 break;
654 657 case 'v':
655 658 verbose++;
656 659 break;
657 660 case 'w':
658 661 use_wall_clock = 1;
659 662 break;
660 663 default:
661 664 usage();
662 665 }
663 666 if (optind >= argc)
664 667 usage();
665 668
666 669 uid = geteuid();
667 670 if (setreuid(uid, uid) < 0)
668 671 die("setreuid: %m");
669 672 box_pid = fork();
670 673 if (box_pid < 0)
671 674 die("fork: %m");
672 675 if (!box_pid)
673 676 box_inside(argc-optind, argv+optind);
@@ -1,20 +1,24
1 1 problem do
2 2 num_tests 2
3 3 full_score 20
4 4 time_limit_each 1
5 5 mem_limit_each 16
6 6 score_each 10
7 7
8 + test 1 do
9 + time_limit 0.5
10 + end
11 +
8 12 run 1 do
9 13 tests 1
10 14 end
11 15
12 16 test 2 do
13 - time_limit 2
17 + time_limit 0.6
14 18 end
15 19
16 20 run 2 do
17 21 tests 2
18 22 end
19 23
20 24 end
@@ -27,53 +27,53
27 27 :comment => /^PASSED/})
28 28 end
29 29
30 30
31 31 it "should produce error message when submission cannot compile" do
32 32 grader_should(:grade => "test1_compile_error.c",
33 33 :on => @problem_test_normal,
34 34 :and_report => {
35 35 :score => 0,
36 36 :comment => 'FAILED: compilation error',
37 37 :compiler_message => /[Ee]rror/})
38 38 end
39 39
40 40 it "should produce timeout error when submission runs forever" do
41 41 @problem_test_timeout = stub(Problem,
42 42 :id => 1, :name => 'test_timeout',
43 43 :full_score => 10)
44 44 grader_should(:grade => "test2_timeout.c",
45 45 :on => @problem_test_timeout,
46 46 :and_report => {
47 47 :score => 0,
48 48 :comment => 'FAILED: TT'})
49 49 end
50 50
51 - it "should produce timeout error correctly when submission runs slower than expected in less than a second" do
52 - @problem_test_timeout = stub(Problem,
51 + it "should produce timeout error correctly with fractional running time and fractional time limits" do
52 + @problem_test_timeout = stub(Problem,
53 53 :id => 1, :name => 'test_timeout',
54 54 :full_score => 20)
55 - grader_should(:grade => "test2_1-5sec.c",
55 + grader_should(:grade => "test2_05sec.c",
56 56 :on => @problem_test_timeout,
57 57 :and_report => {
58 58 :score => 10,
59 59 :comment => 'FAILED: TP'})
60 60 end
61 61
62 62 it "should produce runtime error when submission uses too much static memory" do
63 63 @problem_test_memory = stub(Problem,
64 64 :id => 1, :name => 'test_memory',
65 65 :full_score => 20)
66 66 grader_should(:grade => "add_too_much_memory_static.c",
67 67 :on => @problem_test_memory,
68 68 :and_report => {
69 69 :score => 10,
70 70 :comment => /FAILED: [^P]P/})
71 71 end
72 72
73 73 it "should not allow submission to allocate too much dynamic memory" do
74 74 @problem_test_memory = stub(Problem,
75 75 :id => 1, :name => 'test_memory',
76 76 :full_score => 20)
77 77 grader_should(:grade => "add_too_much_memory_dynamic.c",
78 78 :on => @problem_test_memory,
79 79 :and_report => {
deleted file
You need to be logged in to leave comments. Login now