async def _compiler_build(compiler, time_limit_ns, memory_limit_bytes, process_limit, code, code_type, config): loop = get_event_loop() sandbox, = await get_sandbox(1) try: await compiler.prepare(sandbox, code, code_type, config) output_file = path.join(sandbox.in_dir, 'output') mkfifo(output_file) with socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK) as cgroup_sock: cgroup_sock.bind(path.join(sandbox.in_dir, 'cgroup')) cgroup_sock.listen() build_task = loop.create_task(compiler.build( sandbox, output_file='/in/output', cgroup_file='/in/cgroup', config=config)) others_task = gather(read_pipe(output_file, _MAX_OUTPUT), wait_cgroup(cgroup_sock, build_task, time_limit_ns, time_limit_ns, memory_limit_bytes, process_limit)) package, status = await build_task output, (time_usage_ns, memory_usage_bytes) = await others_task return package, output.decode(encoding='utf-8', errors='replace'), \ time_usage_ns, memory_usage_bytes finally: put_sandbox(sandbox)
async def judge(self, package): loop = get_event_loop() sandbox, = await get_sandbox(1) try: executable = await package.install(sandbox) stdin_file = path.join(sandbox.in_dir, 'stdin') mkfifo(stdin_file) stdout_file = path.join(sandbox.in_dir, 'stdout') mkfifo(stdout_file) stderr_file = path.join(sandbox.in_dir, 'stderr') mkfifo(stderr_file) with socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK) as cgroup_sock: cgroup_sock.bind(path.join(sandbox.in_dir, 'cgroup')) cgroup_sock.listen() execute_task = loop.create_task(executable.execute( sandbox, stdin_file='/in/stdin', stdout_file='/in/stdout', stderr_file='/in/stderr', cgroup_file='/in/cgroup')) others_task = gather( loop.run_in_executor(None, self.do_input, stdin_file), loop.run_in_executor(None, self.do_output, stdout_file), self.read_pipe(stdout_file, MAX_STDERR_SIZE), self.read_pipe(stderr_file, MAX_STDERR_SIZE), wait_cgroup(cgroup_sock, execute_task, self.time_limit_ns, self.time_limit_ns, self.memory_limit_bytes, self.process_limit)) execute_status = await execute_task _, correct, stdout, stderr, (time_usage_ns, memory_usage_bytes) = \ await others_task if memory_usage_bytes >= self.memory_limit_bytes: status = STATUS_MEMORY_LIMIT_EXCEEDED score = 0 elif time_usage_ns >= self.time_limit_ns: status = STATUS_TIME_LIMIT_EXCEEDED score = 0 elif execute_status: status = STATUS_RUNTIME_ERROR score = 0 elif not correct: status = STATUS_WRONG_ANSWER score = 0 else: status = STATUS_ACCEPTED score = self.score return status, score, time_usage_ns, memory_usage_bytes, stdout, stderr except: return 0, 0, 0, 0, 0, 0 finally: put_sandbox(sandbox)
async def judge(self, user_package): loop = get_event_loop() judge_package, message, _, _ = await build( self.judge_lang, await loop.run_in_executor(None, lambda: self.open_judge().read())) if not judge_package: return STATUS_SYSTEM_ERROR, 0, 0, 0, message user_sandbox, judge_sandbox = await get_sandbox(2) try: async def prepare_user_sandbox(): await user_sandbox.reset() return await user_package.install(user_sandbox) async def prepare_judge_sandbox(): await judge_sandbox.reset() return await judge_package.install(judge_sandbox) user_executable, judge_executable = \ await gather(prepare_user_sandbox(), prepare_judge_sandbox()) user_stdin_file = path.join(user_sandbox.in_dir, 'stdin') mkfifo(user_stdin_file) user_stdout_file = path.join(user_sandbox.in_dir, 'stdout') mkfifo(user_stdout_file) judge_stdin_file = path.join(judge_sandbox.in_dir, 'stdin') link(user_stdout_file, judge_stdin_file) user_stderr_file = path.join(user_sandbox.in_dir, 'stderr') mkfifo(user_stderr_file) judge_stdout_file = path.join(judge_sandbox.in_dir, 'stdout') mkfifo(judge_stdout_file) judge_stderr_file = path.join(judge_sandbox.in_dir, 'stderr') mkfifo(judge_stderr_file) judge_extra_file = path.join(judge_sandbox.in_dir, 'extra') mkfifo(judge_extra_file) with socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK) as user_cgroup_sock, \ socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK) as judge_cgroup_sock: user_cgroup_sock.bind(path.join(user_sandbox.in_dir, 'cgroup')) judge_cgroup_sock.bind(path.join(judge_sandbox.in_dir, 'cgroup')) user_cgroup_sock.listen() judge_cgroup_sock.listen() user_execute_task = loop.create_task(user_executable.execute( user_sandbox, stdin_file='/in/stdin', stdout_file='/in/stdout', stderr_file='/in/stderr', cgroup_file='/in/cgroup')) judge_execute_task = loop.create_task(judge_executable.execute( judge_sandbox, stdin_file='/in/stdin', stdout_file='/in/stdout', stderr_file='/in/stderr', extra_file='/in/extra', cgroup_file='/in/cgroup')) others_task = gather( loop.run_in_executor(None, self.do_input, user_stdin_file), loop.run_in_executor(None, self.do_input, judge_extra_file), read_pipe(user_stderr_file, MAX_STDERR_SIZE), read_pipe(judge_stdout_file, MAX_STDERR_SIZE), read_pipe(judge_stderr_file, MAX_STDERR_SIZE), wait_cgroup(user_cgroup_sock, user_execute_task, self.time_ns, self.time_ns, self.memory_bytes, PROCESS_LIMIT), wait_cgroup(judge_cgroup_sock, judge_execute_task, DEFAULT_TIME_NS, self.time_ns + DEFAULT_TIME_NS, DEFAULT_MEMORY_BYTES, PROCESS_LIMIT)) user_execute_status, judge_execute_status = await gather( user_execute_task, judge_execute_task) _, _, user_stderr, judge_stdout, judge_stderr, \ (user_time_usage_ns, user_memory_usage_bytes), \ (judge_time_usage_ns, judge_memory_usage_bytes) = \ await others_task if (judge_execute_status or judge_memory_usage_bytes >= DEFAULT_MEMORY_BYTES or judge_time_usage_ns >= DEFAULT_TIME_NS): status = STATUS_SYSTEM_ERROR score = 0 elif user_memory_usage_bytes >= self.memory_bytes: status = STATUS_MEMORY_LIMIT_EXCEEDED score = 0 elif user_time_usage_ns >= self.time_ns: status = STATUS_TIME_LIMIT_EXCEEDED score = 0 elif user_execute_status: status = STATUS_RUNTIME_ERROR score = 0 else: try: status, score = map(int, judge_stdout.split()) except SystemError: status = STATUS_SYSTEM_ERROR score = 0 return status, score, user_time_usage_ns, user_memory_usage_bytes, user_stderr finally: put_sandbox(user_sandbox, judge_sandbox)