Description:
fix java compiler and runner box does not stop on time because we let box run the script, not the java itself
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r158:19e4c7e30be4 - - 2 files changed: 12 inserted, 4 deleted

@@ -23,141 +23,143
23 23 end
24 24 end
25 25
26 26 C_COMPILER = "/usr/bin/gcc"
27 27 CPLUSPLUS_COMPILER = "/usr/bin/g++"
28 28 PASCAL_COMPILER = "/usr/bin/fpc"
29 29 JAVA_COMPILER = "/usr/bin/javac"
30 30 RUBY_INTERPRETER = "/usr/bin/ruby"
31 31 PYTHON_INTERPRETER = "/usr/bin/python"
32 32 PYTHON_CHECKER = "/usr/bin/pyflakes"
33 33
34 34 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
35 35 CPLUSPLUS_OPTIONS = "-O2 -s -static -DCONTEST -lm -Wall"
36 36 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
37 37 JAVA_OPTIONS = ""
38 38 PYTHON_OPTIONS = ""
39 39
40 40 # Check for the correct number of arguments. Otherwise, print usage.
41 41 if ARGV.length == 0 or ARGV.length > 4
42 42 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
43 43 puts
44 44 puts "<source-file> is defaulted to \"source\"."
45 45 puts "<output-file> is defaulted to \"a.out\"."
46 46 puts "<message-file> is defaulted to \"compiler_message\"."
47 47 puts
48 48 exit(127)
49 49 end
50 50
51 51 PARAMS = {
52 52 :source_file => [1,'source'],
53 53 :output_file => [2,'a.out'],
54 54 :message_file => [3,'compiler_message']
55 55 }
56 56
57 57 params = {}
58 58 params[:prog_lang] = ARGV[0]
59 59 PARAMS.each_key do |param_name|
60 60 index, default = PARAMS[param_name]
61 61 if ARGV.length > index
62 62 params[param_name] = ARGV[index]
63 63 else
64 64 params[param_name] = default
65 65 end
66 66 talk "#{param_name}: #{params[param_name]}"
67 67 end
68 68
69 69 # Remove any remaining output files or message files.
70 70 if FileTest.exists? params[:output_file]
71 71 FileUtils.rm(params[:output_file])
72 72 end
73 73 if FileTest.exists? params[:message_file]
74 74 FileUtils.rm(params[:message_file])
75 75 end
76 76
77 77 # Check if the source file exists before attempt compiling.
78 78 if !FileTest.exists? params[:source_file]
79 79 talk("ERROR: The source file does not exist!")
80 80 open(params[:message_file],"w") do |f|
81 81 f.puts "ERROR: The source file did not exist."
82 82 end
83 83 exit(127)
84 84 end
85 85
86 86 if params[:prog_lang]=='cpp'
87 87 params[:prog_lang] = 'c++'
88 88 end
89 89
90 90 # Compile.
91 91 case params[:prog_lang]
92 92
93 93 when "c"
94 94 command = "#{C_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{C_OPTIONS} 2> #{params[:message_file]}"
95 95 system(command)
96 96
97 97 when "c++"
98 98 command = "#{CPLUSPLUS_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS} 2> #{params[:message_file]}"
99 99 system(command)
100 100
101 101 when "pas"
102 102 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS} > #{params[:message_file]}"
103 103 system(command)
104 104 FileUtils.mv("output", params[:output_file])
105 105
106 106 when "java"
107 107 #rename the file to the public class name
108 108
109 109 #get the class name
110 110 classname = 'DUMMY'
111 111 File.foreach(params[:source_file]) do |line|
112 112 md = /\s*public\s*class\s*(\w*)/.match(line)
113 113 classname=md[1] if md
114 114 end
115 115 system("cp #{params[:source_file]} #{classname}.java")
116 116 command = "#{JAVA_COMPILER} #{classname}.java 2> #{params[:message_file]}"
117 117 system(command)
118 118 if File.exists?(classname + ".class")
119 - File.open(params[:output_file],"w") {|file| file.write("#!/bin/sh\n/usr/bin/java #{classname}\n")}
120 - File.chmod(0755, params[:output_file])
119 + File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
120 + end
121 + if classname == 'DUMMY'
122 + File.open(params[:message_file],"w") {|file| file.write("Cannot find any public class in the source code\n")}
121 123 end
122 124
123 125 when "ruby"
124 126 command = "#{RUBY_INTERPRETER} -c #{params[:source_file]} 2> #{params[:message_file]}"
125 127 if system(command)
126 128 File.open(params[:output_file],"w") do |out_file|
127 129 out_file.puts "#!#{RUBY_INTERPRETER}"
128 130 File.open(params[:source_file],"r").each do |line|
129 131 out_file.print line
130 132 end
131 133 end
132 134 File.chmod(0755, params[:output_file])
133 135 end
134 136
135 137 when "python"
136 138 command = "#{PYTHON_CHECKER} #{params[:source_file]} > #{params[:message_file]}"
137 139 if system(command)
138 140 #compile to python bytecode
139 141 command = "#{PYTHON_INTERPRETER} -m py_compile #{params[:source_file]}"
140 142 puts "compile: #{command}"
141 143 system(command)
142 144 puts "pwd: " + Dir.pwd
143 145 Dir.new('.').each {|file| puts file}
144 146 File.open(params[:output_file],"w") do |out_file|
145 147 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
146 148 end
147 149 File.chmod(0755, params[:output_file])
148 150 end
149 151
150 152 else
151 153 talk("ERROR: Invalid language specified!")
152 154 open(params[:message_file],"w") do |f|
153 155 f.puts "ERROR: Invalid language specified!"
154 156 end
155 157 exit(127)
156 158 end
157 159
158 160 # Report success or failure.
159 161 if FileTest.exists? params[:output_file]
160 162 talk "Compilation was successful!"
161 163 else
162 164 talk "ERROR: Something was wrong during the compilation!"
163 165 end
@@ -1,175 +1,181
1 1 #!/usr/bin/env ruby
2 2
3 3 require 'fileutils'
4 4
5 5 def log(str='')
6 6 if ENV['TALKATIVE']!=nil
7 7 puts str
8 8 end
9 9 if ENV['GRADER_LOGGING']!=nil
10 10 log_fname = ENV['GRADER_LOGGING']
11 11 fp = File.open(log_fname,"a")
12 12 fp.puts("run: #{Time.new.strftime("%H:%M")} #{str}")
13 13 fp.close
14 14 end
15 15 end
16 16
17 17 def extract_time(t)
18 18 # puts "TIME: #{t}"
19 19 if (result=/^(.*)r(.*)u(.*)s/.match(t))
20 20 {:real => result[1], :user => result[2], :sys => result[3]}
21 21 else
22 22 #{:real => 0, :user => 0, :sys => 0}
23 23 #puts "ERROR READING RUNNING TIME: #{t}"
24 24 raise "Error reading running time: #{t}"
25 25 end
26 26 end
27 27
28 28 def compile_box(source,bin)
29 29 system("g++ #{source} -o #{bin}")
30 30 end
31 31
32 32 if ARGV.length < 2 || ARGV.length > 3
33 33 puts "Usage: run <language> <test-num> [<program-name>]"
34 34 exit(127)
35 35 end
36 36
37 37 language = ARGV[0]
38 38 test_num = ARGV[1].to_i
39 39 if ARGV.length > 2
40 40 program_name = ARGV[2]
41 41 else
42 42 program_name = "a.out"
43 43 end
44 44
45 45 problem_home = ENV['PROBLEM_HOME']
46 46 require "#{problem_home}/script/test_dsl.rb"
47 47 load "#{problem_home}/test_cases/all_tests.cfg"
48 48 problem = Problem.get_instance
49 49
50 50 if problem.well_formed? == false
51 51 log "The problem specification is not well formed."
52 52 exit(127)
53 53 end
54 54
55 55 # Check if the test number is okay.
56 56 if test_num <= 0 || test_num > problem.num_tests
57 57 log "You have specified a wrong test number."
58 58 exit(127)
59 59 end
60 60
61 61 #####################################
62 62 # Set the relavant file names here. #
63 63 #####################################
64 64
65 65 input_file_name = "#{problem_home}/test_cases/#{test_num}/input-#{test_num}.txt"
66 66
67 67 #####################################
68 68
69 69 time_limit = problem.get_time_limit test_num
70 70 mem_limit = problem.get_mem_limit(test_num) * 1024
71 71
72 72 # Copy the input file.
73 73 #`cp #{problem_home}/test_cases/#{test_num}/#{input_file_name} .`
74 74
75 75 # check if box is there, if not, compile it!
76 76 if !File.exists?("#{problem_home}/script/box")
77 77 log "WARNING: Compiling box: to increase efficiency, it should be compile manually"
78 78 compile_box("#{problem_home}/script/box.cc",
79 79 "#{problem_home}/script/box")
80 80 end
81 81
82 82 # Hide PROBLEM_HOME
83 83 ENV['PROBLEM_HOME'] = nil
84 84
85 85 # Run the program.
86 86 #run_command = "/usr/bin/time -f \"#{time_output_format}\" 2>run_result #{problem_home}/script/box_new -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
87 87 #
88 88
89 89
90 90
91 91
92 92 case language
93 93 when "java"
94 - # for java, we have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
95 - run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s clone -s wait4 -p /usr/bin/ -p ./ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
94 +
95 + # for java, extract the classname
96 + # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
97 + classname = 'DUMMY'
98 + File.open(program_name,"r").each do |line|
99 + classname = line
100 + end
101 + run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s clone -s wait4 -p /usr/bin/ -p ./ -i #{input_file_name} -o output.txt /usr/bin/java #{classname} 2>run_result"
96 102 when "ruby"
97 103 run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s wait4 -s clone -s set_robust_list -s futex -s sigaltstack -p /dev/urandom -p ./ -p /home/dae/.rvm/rubies/ruby-1.9.2-p320/ -p #{problem_home}/ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
98 104 when "python"
99 105 #this code just run without any checking
100 106 run_command = "#{problem_home}/script/box -T -t #{time_limit} -p #{problem_home}/ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
101 107 else # for c++, pascal, we do the normal checking
102 108 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
103 109 end
104 110
105 111
106 112 log "Running test #{test_num}..."
107 113 log run_command
108 114 log
109 115 system(run_command)
110 116
111 117 # Restore PROBLEM_HOME
112 118 ENV['PROBLEM_HOME'] = problem_home
113 119
114 120 # Create the result file.
115 121 result_file = File.new("result", "w")
116 122 comment_file = File.new("comment", "w")
117 123
118 124 # Check if the program actually produced any output.
119 125 run_result_file = File.new("run_result", "r")
120 126 run_result = run_result_file.readlines
121 127 run_result_file.close
122 128
123 129 run_stat = run_result[run_result.length-1]
124 130 running_time = extract_time(run_stat)
125 131
126 132 report = lambda{ |status, points, comment|
127 133 result_file.write status.strip
128 134 result_file.write "\n"
129 135 result_file.write points.to_s.strip
130 136 result_file.write "\n"
131 137 result_file.write run_stat.strip
132 138 result_file.write "\n"
133 139 result_file.close
134 140 FileUtils.rm "run_result"
135 141 # `rm output.txt` --- keep the output
136 142
137 143 comment_file.write comment
138 144
139 145 # added for debuggin --- jittat
140 146 comment_file.write "--run-result--\n"
141 147 run_result.each do |l|
142 148 comment_file.write l
143 149 end
144 150
145 151 comment_file.close
146 152
147 153 log "Done!"
148 154 exit(0)
149 155 }
150 156
151 157 if run_result[0][0,2] != "OK"
152 158 log "There was a runtime error."
153 159 report.call(run_result[0], 0, "No comment.\n")
154 160 end
155 161
156 162 if running_time[:user].to_f > time_limit
157 163 log "Time limit exceeded."
158 164 report.call("Time limit exceeded", 0, "No comment.\n")
159 165 end
160 166
161 167 # Run 'check' to evaluate the output.
162 168 #puts "There was no runtime error. Proceed to checking the output."
163 169 check_command = "#{problem_home}/script/check #{language} #{test_num}"
164 170 log "Checking the output..."
165 171 log check_command
166 172 if not system(check_command)
167 173 log "Problem with check script"
168 174 report.call("Incorrect",0,"Check script error.\n")
169 175 exit(127)
170 176 end
171 177
172 178 check_file = File.new("check_result", "r")
173 179 check_file_lines = check_file.readlines
174 180
175 181 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
You need to be logged in to leave comments. Login now