module KGrader class Jail def initialize(root) @root = root @salt = nil end def reset FileUtils.rm_rf @root end def init FileUtils.mkdir_p @root @salt = rand(100000000).to_s end def stage(source, target) FileUtils.cp source, File.join(@root, target) end def exec(command, logpath) pid = execute command, logpath Process.waitpid pid, 0 $?.exited? && $?.exitstatus == 0 end def run_test(script, logpath) grade_rd, grade_wr = IO.pipe cmt_rd, cmt_wr = IO.pipe command = ['ruby', '-r', '../lib/kgrader/runtime.rb', script, @salt] pid = execute command, logpath do |options| [grade_rd, cmt_rd].each &:close options[3] = grade_wr options[4] = cmt_wr end [grade_wr, cmt_wr].each &:close Process.waitpid pid, 0 grade = grade_rd.read.strip.to_i comments = cmt_rd.read.split("\n") [grade_rd, cmt_rd].each &:close return grade, comments end private def execute(command, logpath) Process.fork do fp = File.open(logpath, 'a') Dir.chdir @root options = { :in => :close, :out => fp, :err => fp, :close_others => true, :rlimit_nproc => 64 } yield options if block_given? Process.exec *command, options end end end end