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