Exemple #1
0
class SandboxProcessServer:
    def __init__(self, *, sandbox_dir, executable):
        self.executable = executable

        self.boundary = PipeBoundary(sandbox_dir)
        self.boundary.create_channel(SANDBOX_PROCESS_CHANNEL)
        self.boundary.create_queue(SANDBOX_REQUEST_QUEUE)

        self.done = False
        self.process = None

        self.process_exit_stack = ExitStack()

    def run(self):
        logger.debug("starting process...")

        with self.boundary.open_channel(SANDBOX_PROCESS_CHANNEL,
                                        PipeBoundarySide.SERVER) as pipes:
            connection = SandboxProcessConnection(**pipes)
            self.process = self.process_exit_stack.enter_context(
                self.executable.run(connection))

        logger.debug("process started")

        while not self.done:
            logger.debug("handling requests...")
            self.boundary.handle_request(
                SANDBOX_REQUEST_QUEUE,
                self.handle_request,
            )

    def handle_request(self, *, wait):
        assert not self.done
        assert wait in ("0", "1")

        time_usage = self.executable.get_time_usage(self.process)
        memory_usage = self.executable.get_memory_usage(self.process)

        message = stacktrace = ""
        if wait == "1":
            self.done = True
            self.process = None
            try:
                self.process_exit_stack.close()
            except AlgorithmRuntimeError as e:
                message, stacktrace = e.args

        return {
            "error": message,
            "stacktrace": stacktrace,
            "time_usage": str(time_usage),
            "memory_usage": str(memory_usage),
        }
Exemple #2
0
class SandboxProcessClient:
    def __init__(self, directory):
        self.boundary = PipeBoundary(directory)

    def get_info(self, *, wait=False):
        response = self.boundary.send_request(
            SANDBOX_REQUEST_QUEUE,
            wait=str(int(bool(wait))),
        )

        response["time_usage"] = float(response["time_usage"])
        response["memory_usage"] = int(response["memory_usage"])
        return SandboxProcessInfo(**response)

    @contextmanager
    def connect(self):
        logger.debug("connecting to process...")
        with self.boundary.open_channel(SANDBOX_PROCESS_CHANNEL, PipeBoundarySide.CLIENT) as pipes:
            yield SandboxProcessConnection(**pipes)

    def wait(self):
        return self.get_info(wait=True)