From 6fb245874620a3e1f7e3450c3579a60a7a46bf18 Mon Sep 17 00:00:00 2001 From: Kento HASEGAWA Date: Fri, 26 Jul 2019 22:37:03 +0900 Subject: [PATCH] Add support for stopping solver --- roles/solver.py | 26 ++---------- solvers/SampleSolver/main.py | 80 +++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 25 deletions(-) diff --git a/roles/solver.py b/roles/solver.py index 8668abd..113828a 100644 --- a/roles/solver.py +++ b/roles/solver.py @@ -6,23 +6,6 @@ import sys import time import threading -class StoppableThread(threading.Thread): - - def __init__(self, target, args=()): - super(StoppableThread, self).__init__(target=target, args=args) - self._status = 'running' - def stop(self): - if self.is_running(): - self._status = 'stopping' - def stopped(self): - self._status = 'stopped' - def is_running(self): - return (self._status == 'running') - def is_stopping(self): - return (self._status == 'stopping') - def is_stopped(self): - return (self._status == 'stopped') - class Solver(object): def __init__(self, config): @@ -42,7 +25,6 @@ class Solver(object): start_time = time.time() solution = self.solver.solve(params) end_time = time.time() - self.thread.stopped() elapsed_time = end_time - start_time @@ -74,7 +56,8 @@ class Solver(object): if self.thread is None: print("I: Solver started") - self.thread = StoppableThread(target=self.solve, args=(params, )) + # self.thread = StoppableThread(target=self.solve, args=(params, )) + self.thread = threading.Thread(name='solver', target=self.solve, args=(params, ), daemon=True) self.thread.start() return {'status': 'started'} else: @@ -83,10 +66,7 @@ class Solver(object): def stop_solver(self): if self.thread is not None: - if self.thread.is_running(): - self.thread.stop() - self.thread.join(0.1) - self.thread = None + self.solver.stop() return {'status': 'stopped'} diff --git a/solvers/SampleSolver/main.py b/solvers/SampleSolver/main.py index 0532853..dfd65d8 100644 --- a/solvers/SampleSolver/main.py +++ b/solvers/SampleSolver/main.py @@ -1,6 +1,82 @@ +import os +import subprocess + +proc = None +stop_flag = False + +def stop(): + global proc + global stop_flag + + stop_flag = True + if not proc is None: + proc.terminate() + print('stopped') + def solve(params): - print("This is a sample solver.") - return {'solution': 'aaa!'} + global proc + global stop_flag + + stop_flag = False + + # 必要な変数があるか確認 + assert('problem' in params) + assert('timeout' in params) + + problem = params['problem'] + timeout = params['timeout'] + + print(problem) + + # ソルバを実行するためのコマンドを指定 + command = f'sleep 100' + cmds = command.split() + + if stop_flag:return { + 'status': 'stopped', + 'solution': '', + } + + # ソルバを実行する準備 + proc = subprocess.Popen( + cmds, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE + ) + + print(' === start waiting === ') + # ソルバを実行,タイムアウトしたらTimeoutExpiredになる + try: + outs, errs = proc.communicate(timeout=timeout) + status = 'done' + except subprocess.TimeoutExpired: + proc.kill() + outs, errs = proc.communicate() + status = 'timeout' + finally: + returncode = proc.returncode + outs = outs.decode() + errs = errs.decode() + + # 解けたか解けなかったかによってstatusを適当なものに設定する + # return + if returncode == 0: + if outs.startswith('SIZE'): + status = 'done' + solution = outs + else: + status = 'failed' + solution = outs + else: + status = 'failed' + solution = '' + + # 答えを返す + return { + 'status': status, + 'solution': solution, + # 'elapsed_time': 0.0 # 必要ならば足す,無ければシステム側で自動算出 + } def main(params): solve(a) -- 2.22.0