示例#1
0
    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
示例#2
0
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)