def __init__(self, command: str, envvars=dict(), timeout=30, log=False, socket=False): environment = dict(os.environ) environment.update(envvars) self._workdir = tempfile.mkdtemp() self._returncode = None self._socket = None if socket: for port in range(PORT_POOL_MIN, PORT_POOL_MAX): socket = open_local_port(port) if not socket is None: self._socket = socket break environment["TRAX_SOCKET"] = "{}".format(port) logger.debug("Running process: %s", command) if sys.platform.startswith("win"): self._process = subprocess.Popen( command, cwd=self._workdir, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=environment, bufsize=0) else: self._process = subprocess.Popen( shlex.split(command), shell=False, cwd=self._workdir, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=environment) self._timeout = timeout self._client = None self._watchdog_counter = 0 self._watchdog = Thread(target=self._watchdog_loop) self._watchdog.start() self._watchdog_reset(True) try: if socket: self._client = Client(stream=self._socket.fileno(), timeout=30, log=log) else: self._client = Client( stream=(self._process.stdin.fileno(), self._process.stdout.fileno()), log=log ) except TraxException as e: self.terminate() self._watchdog_reset(False) raise e self._watchdog_reset(False) self._has_vot_wrapper = not self._client.get("vot") is None
class TrackerProcess(object): def __init__(self, command: str, envvars=dict(), timeout=30, log=False, socket=False): environment = dict(os.environ) environment.update(envvars) self._workdir = tempfile.mkdtemp() self._returncode = None self._socket = None if socket: for port in range(PORT_POOL_MIN, PORT_POOL_MAX): socket = open_local_port(port) if not socket is None: self._socket = socket break environment["TRAX_SOCKET"] = "{}".format(port) logger.debug("Running process: %s", command) if sys.platform.startswith("win"): self._process = subprocess.Popen(command, cwd=self._workdir, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=environment, bufsize=0) else: self._process = subprocess.Popen(shlex.split(command), shell=False, cwd=self._workdir, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=environment) self._timeout = timeout self._client = None self._watchdog_lock = Lock() self._watchdog_counter = 0 self._watchdog = Thread(target=self._watchdog_loop) self._watchdog.start() self._watchdog_reset(True) try: if socket: self._client = Client(stream=self._socket.fileno(), timeout=30, log=log) else: self._client = Client(stream=(self._process.stdin.fileno(), self._process.stdout.fileno()), log=log) except TraxException as e: self.terminate() self._watchdog_reset(False) raise e self._watchdog_reset(False) self._has_vot_wrapper = not self._client.get("vot") is None def _watchdog_reset(self, enable=True): if self._watchdog_counter == 0: return if enable: self._watchdog_counter = self._timeout * 10 else: self._watchdog_counter = -1 def _watchdog_loop(self): while self.alive: time.sleep(0.1) if self._watchdog_counter < 0: continue self._watchdog_counter = self._watchdog_counter - 1 if not self._watchdog_counter: logger.warning("Timeout reached, terminating tracker") self.terminate() break @property def has_vot_wrapper(self): return self._has_vot_wrapper @property def returncode(self): return self._returncode @property def workdir(self): return self._workdir @property def interrupted(self): return self._watchdog_counter == 0 @property def alive(self): if self._process is None: return False self._returncode = self._process.returncode return self._returncode is None def initialize(self, frame: Frame, region: Region, properties: dict = None) -> Tuple[Region, dict, float]: if not self.alive: raise TraxException("Tracker not alive") if properties is None: properties = dict() tlist = convert_frame(frame, self._client.channels) tregion = convert_region(region) self._watchdog_reset(True) region, properties, elapsed = self._client.initialize( tlist, tregion, properties) self._watchdog_reset(False) return convert_traxregion(region), properties.dict(), elapsed def frame( self, frame: Frame, properties: dict = dict()) -> Tuple[Region, dict, float]: if not self.alive: raise TraxException("Tracker not alive") tlist = convert_frame(frame, self._client.channels) self._watchdog_reset(True) region, properties, elapsed = self._client.frame(tlist, properties) self._watchdog_reset(False) return convert_traxregion(region), properties.dict(), elapsed def terminate(self): with self._watchdog_lock: if not self.alive: return if not self._client is None: self._client.quit() try: self._process.wait(3) except subprocess.TimeoutExpired: pass # Flush remaining output #while True: # line = self._process.stdout.readline() # if not line is None and not self._client._logger is None: # self._client._logger.handle(line.decode("utf-8")) if self._process.returncode is None: self._process.terminate() try: self._process.wait(3) except subprocess.TimeoutExpired: pass if self._process.returncode is None: self._process.kill() if not self._socket is None: self._socket.close() self._returncode = self._process.returncode self._client = None self._process = None def __del__(self): if hasattr(self, "_workdir"): shutil.rmtree(self._workdir, ignore_errors=True)