2016-01-21 23:22:42 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
|
|
# Copyright (C) 2015-2016 Andrew Hamilton. All rights reserved.
|
|
|
|
|
# Licensed under the Artistic License 2.0.
|
|
|
|
|
|
2016-03-10 00:36:59 +00:00
|
|
|
import asyncio
|
2016-01-21 23:22:42 +00:00
|
|
|
import os
|
2016-03-10 00:36:59 +00:00
|
|
|
import signal
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
import psutil
|
2016-01-21 23:22:42 +00:00
|
|
|
|
|
|
|
|
import tools
|
|
|
|
|
|
|
|
|
|
|
2016-03-10 00:36:59 +00:00
|
|
|
def _make_process_nicest(pid):
|
|
|
|
|
process = psutil.Process(pid)
|
|
|
|
|
process.nice(19)
|
|
|
|
|
process.ionice(psutil.IOPRIO_CLASS_IDLE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Worker:
|
|
|
|
|
|
|
|
|
|
def __init__(self, sandbox, is_already_paused, is_being_tested):
|
|
|
|
|
self.sandbox = sandbox
|
|
|
|
|
self.is_already_paused = is_already_paused
|
|
|
|
|
self.is_being_tested = is_being_tested
|
|
|
|
|
self.result = None
|
|
|
|
|
self.process = None
|
|
|
|
|
self.child_pid = None
|
|
|
|
|
|
2016-10-16 12:10:22 +02:00
|
|
|
async def create_process(self):
|
2016-03-12 23:16:52 +00:00
|
|
|
command = [__file__]
|
|
|
|
|
if self.sandbox is not None:
|
|
|
|
|
command = self.sandbox.command(command)
|
2016-03-10 00:36:59 +00:00
|
|
|
create = asyncio.create_subprocess_exec(
|
|
|
|
|
*command, stdin=asyncio.subprocess.PIPE,
|
|
|
|
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
2016-10-16 12:10:22 +02:00
|
|
|
self.process = await create
|
|
|
|
|
pid_line = await self.process.stdout.readline()
|
2016-03-10 00:36:59 +00:00
|
|
|
self.child_pid = int(pid_line.strip())
|
|
|
|
|
|
2016-10-16 12:10:22 +02:00
|
|
|
async def run_tool(self, path, tool):
|
2016-03-10 00:36:59 +00:00
|
|
|
self.process.stdin.write(("%s\n%s\n" %
|
|
|
|
|
(tool.__qualname__, path)).encode("utf-8"))
|
2016-10-16 12:10:22 +02:00
|
|
|
data = await self.process.stdout.readline()
|
2016-03-10 00:36:59 +00:00
|
|
|
return tools.Status(int(data))
|
|
|
|
|
|
2016-10-16 12:10:22 +02:00
|
|
|
async def job_runner(self, summary, log, jobs_added_event,
|
2016-03-10 00:36:59 +00:00
|
|
|
appearance_changed_event):
|
2016-10-16 12:10:22 +02:00
|
|
|
await self.create_process()
|
2016-03-10 00:36:59 +00:00
|
|
|
_make_process_nicest(self.child_pid)
|
|
|
|
|
while True:
|
2016-10-16 12:10:22 +02:00
|
|
|
await jobs_added_event.wait()
|
2016-03-10 00:36:59 +00:00
|
|
|
while True:
|
|
|
|
|
# _regulate_temperature(log) # My fan is broken
|
|
|
|
|
try:
|
|
|
|
|
self.result = summary.get_closest_placeholder()
|
|
|
|
|
except StopIteration:
|
|
|
|
|
self.result = None
|
|
|
|
|
if summary.result_total == summary.completed_total:
|
|
|
|
|
log.log_message("All results are up to date.")
|
|
|
|
|
if self.is_being_tested:
|
|
|
|
|
os.kill(os.getpid(), signal.SIGINT)
|
|
|
|
|
break
|
2016-10-16 12:10:22 +02:00
|
|
|
await self.result.run(log, appearance_changed_event,
|
2016-03-10 00:36:59 +00:00
|
|
|
self)
|
|
|
|
|
summary.completed_total += 1
|
|
|
|
|
jobs_added_event.clear()
|
|
|
|
|
|
|
|
|
|
def pause(self):
|
|
|
|
|
if self.result is not None and \
|
|
|
|
|
self.result.status == tools.Status.running:
|
|
|
|
|
os.kill(self.child_pid, signal.SIGSTOP)
|
|
|
|
|
self.result.set_status(tools.Status.paused)
|
|
|
|
|
|
|
|
|
|
def continue_(self):
|
|
|
|
|
if self.result is not None and \
|
|
|
|
|
self.result.status == tools.Status.paused:
|
|
|
|
|
self.result.set_status(tools.Status.running)
|
|
|
|
|
os.kill(self.child_pid, signal.SIGCONT)
|
|
|
|
|
|
|
|
|
|
|
2016-01-21 23:22:42 +00:00
|
|
|
def main():
|
|
|
|
|
print(os.getpid(), flush=True)
|
|
|
|
|
while True:
|
|
|
|
|
tool_name, path = input(), input()
|
|
|
|
|
tool = getattr(tools, tool_name)
|
2016-02-13 18:48:53 +00:00
|
|
|
result = tools.Result(path, tool)
|
2016-01-21 23:22:42 +00:00
|
|
|
status, result.result = tools.run_tool_no_error(path, tool)
|
2016-02-08 19:41:47 +00:00
|
|
|
print(status.value, flush=True)
|
2016-01-21 23:22:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|