def compile_(language_item, src_path, exe_path): 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: logger.error("Compiler error") logger.error(output) raise JudgeClientError("Error running compiler in lrun") # 返回值不为 0 或者 stderr 中 lrun 的输出之前有 erro r字符串 # 判断 error 字符串的原因是链接的时候可能会有一些不推荐使用的函数的的警告, # 但是 -w 参数并不能关闭链接时的警告 if status or "error" in output[0:output_start]: raise CompileError(output[0:output_start]) parse_result = parse_lrun_output(output[output_start:]) if parse_result["exit_code"] or parse_result["term_sig"] or parse_result["siginaled"] or parse_result["exceed"]: logger.error("Compiler error") logger.error(output) raise CompileError("Compile error") return exe_path
def _parse_lrun_output(self, output): # 要注意的是 lrun把结果输出到了stderr,所以有些情况下lrun的输出可能与程序的一些错误输出的混合的,要先分离一下 error = None # 倒序找到MEMORY的位置,lrun的 MEMORY 输出后面有3个空格,而 EXCEEDED 也有可能是MEMORY,所以需要判断空格 output_start = output.rfind("MEMORY ") if output_start == -1: logger.error("Lrun result parse error") logger.error(output) raise JudgeClientError("Lrun result parse error") # 如果不是0,说明lrun输出前面有输出,也就是程序的stderr有内容 if output_start != 0: error = output[0:output_start] # 分离出lrun的输出 output = output[output_start:] return error, parse_lrun_output(output)