给编译器也增加超时保护

比如使用include</dev/random>就可能导致编译器卡死,增加了一个编译超时。
重命名了exception模块
整理了部分格式
This commit is contained in:
virusdefender 2015-07-07 21:04:38 +08:00
parent d85ed0a2ec
commit dd7fe6ee44
5 changed files with 68 additions and 81 deletions

View File

@ -8,9 +8,8 @@ from settings import max_running_number, lrun_gid, lrun_uid, judger_workspace
from language import languages
from result import result
from compiler import compile_
class JudgeClientException(Exception):
pass
from judge_exceptions import JudgeClientException, CompileError
from utils import parse_lrun_output
# 下面这个函数作为代理访问实例变量否则Python2会报错是Python2的已知问题
@ -51,21 +50,6 @@ class JudgeClient(object):
raise JudgeClientException("Test case config file not found")
except ValueError:
raise JudgeClientException("Test case config file format error")
# return {"test_case_number": 2,
# "test_cases":
# {
# "1": {"input_name": "1.in",
# "output_name": "1.out",
# "output_md5": "b10a8db164e0754105b7a99be72e3fe5",
# "output_size": 100},
#
# "2": {"input_name": "2.in",
# "output_name": "2.out",
# "output_md5": "3e25960a79dbc69b674cd4ec67a72c62",
# "output_size": 100}
# },
# "output_total_size": 200
# }
def _generate_command(self, test_case_id):
"""
@ -104,41 +88,8 @@ class JudgeClient(object):
error = output[0:output_start]
# 分离出lrun的输出
output = output[output_start:]
lines = output.split("\n")
if len(lines) != 7:
raise JudgeClientException("Lrun result parse error")
result = {}
# 将lrun输出的各种带下划线 不带下划线的字符串统一处理
translate = {"MEMORY": "memory",
"CPUTIME": "cpu_time",
"CPU_TIME": "cpu_time",
"REALTIME": "real_time",
"REAL_TIME": "real_time",
"TERMSIG": "term_sig",
"SIGNALED": "siginaled",
"EXITCODE": "exit_code",
"EXCEED": "exceed"}
for line in lines:
name = line[:9].strip(" ")
value = line[9:]
if name == "MEMORY":
result[translate[name]] = int(value)
elif name == "CPUTIME":
result[translate[name]] = int(float(value) * 1000)
elif name == "REALTIME":
result[translate[name]] = int(float(value) * 1000)
elif name == "EXITCODE":
result[translate[name]] = int(value)
elif name == "TERMSIG":
result[translate[name]] = int(value)
elif name == "SIGNALED":
result[translate[name]] = int(value)
elif name == "EXCEED":
if value == "none":
result[translate[name]] = None
else:
result[translate[name]] = translate[value]
return error, result
return error, parse_lrun_output(output)
def _compare_output(self, test_case_id):
test_case_md5 = self._test_case_info["test_cases"][str(test_case_id)]["output_md5"]
@ -188,7 +139,6 @@ class JudgeClient(object):
return run_result
# 下面就是代码正常运行了 需要判断代码的输出是否正确
if self._compare_output(test_case_id):
run_result["result"] = result["accepted"]
else:
@ -210,6 +160,7 @@ class JudgeClient(object):
try:
results.append(item.get())
except Exception as e:
# todo logging
print e
results.append({"result": result["system_error"]})
return results
@ -225,11 +176,10 @@ class JudgeClient(object):
c_src = r"""
#include <stdio.h>
#include </dev/random>
int main()
{
FILE *fp;
fp = NULL;
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
@ -256,7 +206,7 @@ int main()
java_src = r"""
import java.io.*;
import java.util.*;
11
public class Main
{
public static void main(String[] args)
@ -279,16 +229,20 @@ def judge(languege_code, source_string):
f.write(source_string)
f.close()
try:
exe_path = compile_(languages[str(languege_code)], src_path, judger_workspace)
except Exception as e:
print e
return [{"result": result["compile_error"]}]
client = JudgeClient(language_code=languege_code,
exe_path=compile_(languages[str(languege_code)],
src_path,
judger_workspace),
exe_path=exe_path,
max_cpu_time=1000000,
max_real_time=200000,
max_memory=1000,
test_case_dir="/var/test_cases/1/")
print client.run()
return client.run()
judge(1, c_src)
judge(2, cpp_src)
judge(3, java_src)
print judge(1, c_src)
print judge(2, cpp_src)
print judge(3, java_src)

View File

@ -1,14 +1,37 @@
# coding=utf-8
import commands
class CompileError(Exception):
pass
from settings import lrun_uid, lrun_gid
from judge_exceptions import CompileError
from utils import parse_lrun_output
def compile_(language_item, src_path, exe_path):
command = language_item["compile_command"].format(src_path=src_path, exe_path=exe_path)
status, output = commands.getstatusoutput(command)
if status:
raise CompileError(output)
compile_command = language_item["compile_command"].format(src_path=src_path, exe_path=exe_path)
# 防止编译器卡死 或者 include </dev/random>等
execute_command = "lrun" + \
" --max-real-time 5" + \
" --uid " + str(lrun_uid) + \
" --gid " + str(lrun_gid) + \
" " + \
compile_command + \
" 3>&2"
status, output = commands.getstatusoutput(execute_command)
output_start = output.rfind("MEMORY")
if output_start == -1:
raise CompileError("Error running compiler in lrun")
# 返回值不为0 或者 stderr中lrun的输出之前有东西
if status or output_start:
raise CompileError(output[0:output_start])
parse_result = parse_lrun_output(output)
if parse_result["exit_code"] or parse_result["term_sig"] or parse_result["siginaled"] or parse_result["exceed"]:
raise CompileError("Compile error")
# 对于正常编译和超时等其他的错误
return exe_path

View File

@ -0,0 +1,9 @@
# coding=utf-8
class JudgeClientException(Exception):
pass
class CompileError(Exception):
pass

View File

@ -1,7 +1,6 @@
# coding=utf-8
languages = {
"1": {
"name": "c",

View File

@ -1,12 +1,14 @@
# coding=utf-8
result = {"accepted": 0,
"runtime_error": 1,
"time_limit_exceeded": 2,
"memory_limit_exceeded": 3,
"compile_error": 4,
"format_error": 5,
"wrong_answer": 6,
"system_error": 7,
"waiting": 8}
result = {
"accepted": 0,
"runtime_error": 1,
"time_limit_exceeded": 2,
"memory_limit_exceeded": 3,
"compile_error": 4,
"format_error": 5,
"wrong_answer": 6,
"system_error": 7,
"waiting": 8
}