mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-11-04 14:49:58 +08:00
给编译器也增加超时保护
比如使用include</dev/random>就可能导致编译器卡死,增加了一个编译超时。 重命名了exception模块 整理了部分格式
This commit is contained in:
parent
d85ed0a2ec
commit
dd7fe6ee44
@ -8,9 +8,8 @@ from settings import max_running_number, lrun_gid, lrun_uid, judger_workspace
|
|||||||
from language import languages
|
from language import languages
|
||||||
from result import result
|
from result import result
|
||||||
from compiler import compile_
|
from compiler import compile_
|
||||||
|
from judge_exceptions import JudgeClientException, CompileError
|
||||||
class JudgeClientException(Exception):
|
from utils import parse_lrun_output
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# 下面这个函数作为代理访问实例变量,否则Python2会报错,是Python2的已知问题
|
# 下面这个函数作为代理访问实例变量,否则Python2会报错,是Python2的已知问题
|
||||||
@ -51,21 +50,6 @@ class JudgeClient(object):
|
|||||||
raise JudgeClientException("Test case config file not found")
|
raise JudgeClientException("Test case config file not found")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise JudgeClientException("Test case config file format error")
|
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):
|
def _generate_command(self, test_case_id):
|
||||||
"""
|
"""
|
||||||
@ -104,41 +88,8 @@ class JudgeClient(object):
|
|||||||
error = output[0:output_start]
|
error = output[0:output_start]
|
||||||
# 分离出lrun的输出
|
# 分离出lrun的输出
|
||||||
output = output[output_start:]
|
output = output[output_start:]
|
||||||
lines = output.split("\n")
|
|
||||||
if len(lines) != 7:
|
return error, parse_lrun_output(output)
|
||||||
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
|
|
||||||
|
|
||||||
def _compare_output(self, test_case_id):
|
def _compare_output(self, test_case_id):
|
||||||
test_case_md5 = self._test_case_info["test_cases"][str(test_case_id)]["output_md5"]
|
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
|
return run_result
|
||||||
|
|
||||||
# 下面就是代码正常运行了 需要判断代码的输出是否正确
|
# 下面就是代码正常运行了 需要判断代码的输出是否正确
|
||||||
|
|
||||||
if self._compare_output(test_case_id):
|
if self._compare_output(test_case_id):
|
||||||
run_result["result"] = result["accepted"]
|
run_result["result"] = result["accepted"]
|
||||||
else:
|
else:
|
||||||
@ -210,6 +160,7 @@ class JudgeClient(object):
|
|||||||
try:
|
try:
|
||||||
results.append(item.get())
|
results.append(item.get())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# todo logging
|
||||||
print e
|
print e
|
||||||
results.append({"result": result["system_error"]})
|
results.append({"result": result["system_error"]})
|
||||||
return results
|
return results
|
||||||
@ -225,11 +176,10 @@ class JudgeClient(object):
|
|||||||
|
|
||||||
c_src = r"""
|
c_src = r"""
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include </dev/random>
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
fprintf(fp, "This is testing for fprintf...\n");
|
fprintf(fp, "This is testing for fprintf...\n");
|
||||||
fputs("This is testing for fputs...\n", fp);
|
fputs("This is testing for fputs...\n", fp);
|
||||||
@ -256,7 +206,7 @@ int main()
|
|||||||
java_src = r"""
|
java_src = r"""
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
11
|
||||||
public class Main
|
public class Main
|
||||||
{
|
{
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
@ -279,16 +229,20 @@ def judge(languege_code, source_string):
|
|||||||
f.write(source_string)
|
f.write(source_string)
|
||||||
f.close()
|
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,
|
client = JudgeClient(language_code=languege_code,
|
||||||
exe_path=compile_(languages[str(languege_code)],
|
exe_path=exe_path,
|
||||||
src_path,
|
|
||||||
judger_workspace),
|
|
||||||
max_cpu_time=1000000,
|
max_cpu_time=1000000,
|
||||||
max_real_time=200000,
|
max_real_time=200000,
|
||||||
max_memory=1000,
|
max_memory=1000,
|
||||||
test_case_dir="/var/test_cases/1/")
|
test_case_dir="/var/test_cases/1/")
|
||||||
print client.run()
|
return client.run()
|
||||||
|
|
||||||
judge(1, c_src)
|
print judge(1, c_src)
|
||||||
judge(2, cpp_src)
|
print judge(2, cpp_src)
|
||||||
judge(3, java_src)
|
print judge(3, java_src)
|
||||||
@ -1,14 +1,37 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import commands
|
import commands
|
||||||
|
|
||||||
|
from settings import lrun_uid, lrun_gid
|
||||||
class CompileError(Exception):
|
from judge_exceptions import CompileError
|
||||||
pass
|
from utils import parse_lrun_output
|
||||||
|
|
||||||
|
|
||||||
def compile_(language_item, src_path, exe_path):
|
def compile_(language_item, src_path, exe_path):
|
||||||
command = language_item["compile_command"].format(src_path=src_path, exe_path=exe_path)
|
compile_command = language_item["compile_command"].format(src_path=src_path, exe_path=exe_path)
|
||||||
status, output = commands.getstatusoutput(command)
|
|
||||||
if status:
|
# 防止编译器卡死 或者 include </dev/random>等
|
||||||
raise CompileError(output)
|
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
|
return exe_path
|
||||||
|
|||||||
9
judge/judge_exceptions.py
Normal file
9
judge/judge_exceptions.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
|
||||||
|
class JudgeClientException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CompileError(Exception):
|
||||||
|
pass
|
||||||
@ -1,7 +1,6 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
languages = {
|
languages = {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "c",
|
"name": "c",
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
|
|
||||||
result = {"accepted": 0,
|
result = {
|
||||||
"runtime_error": 1,
|
"accepted": 0,
|
||||||
"time_limit_exceeded": 2,
|
"runtime_error": 1,
|
||||||
"memory_limit_exceeded": 3,
|
"time_limit_exceeded": 2,
|
||||||
"compile_error": 4,
|
"memory_limit_exceeded": 3,
|
||||||
"format_error": 5,
|
"compile_error": 4,
|
||||||
"wrong_answer": 6,
|
"format_error": 5,
|
||||||
"system_error": 7,
|
"wrong_answer": 6,
|
||||||
"waiting": 8}
|
"system_error": 7,
|
||||||
|
"waiting": 8
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user