def _start_monitors(self): self.stdout_monitor = PipeMonitor(self._proc.stdout, self._stdout_handler) self.stdout_monitor.start() self.stderr_monitor = PipeMonitor(self._proc.stderr, self._stderr_handler) self.stderr_monitor.start()
def start(self): self._dbmon_proc = Popen(["dada_dbmonitor", "-k", self._key], stdout=PIPE, stderr=PIPE, shell=False, close_fds=True) self._mon_thread = PipeMonitor(self._dbmon_proc.stderr, self._stdout_parser) self._mon_thread.start()
class DbMonitor(object): def __init__(self, key, callback=None): self._key = key self._callback = callback self._dbmon_proc = None self._mon_thread = None def _stdout_parser(self, line): line = line.strip() try: values = map(int, line.split()) free, full, clear, written, read = values[5:] fraction = float(full) / (full + free) params = { "fraction-full": fraction, "written": written, "read": read } log.debug("{} params: {}".format(self._key, params)) if self._callback: self._callback(params) return params except Exception as error: log.warning("Unable to parse line with error".format(str(error))) return None def start(self): self._dbmon_proc = Popen(["dada_dbmonitor", "-k", self._key], stdout=PIPE, stderr=PIPE, shell=False, close_fds=True) self._mon_thread = PipeMonitor(self._dbmon_proc.stderr, self._stdout_parser) self._mon_thread.start() def stop(self): self._dbmon_proc.kill() self._mon_thread.join()
class ManagedProcess(object): def __init__(self, cmdlineargs, stdout_handler=None, stderr_handler=None): self._proc = Popen(map(str, cmdlineargs), stdout=PIPE, stderr=PIPE, shell=False, close_fds=True) if stdout_handler: self._stdout_handler = stdout_handler else: self._stdout_handler = lambda line: log.debug(line.strip()) if stderr_handler: self._stderr_handler = stderr_handler else: self._stderr_handler = lambda line: log.warning(line.strip()) self.stdout_monitor = None self.stderr_monitor = None self.eop_monitor = None self._start_monitors() @property def pid(self): return self._proc.pid def is_alive(self): return self._proc.poll() is None def _start_monitors(self): self.stdout_monitor = PipeMonitor(self._proc.stdout, self._stdout_handler) self.stdout_monitor.start() self.stderr_monitor = PipeMonitor(self._proc.stderr, self._stderr_handler) self.stderr_monitor.start() def _stop_monitors(self): self.stdout_monitor.join() self.stdout_monitor = None self.stderr_monitor.join() self.stderr_monitor = None def terminate(self, timeout=5): start = time.time() while self._proc.poll() is None: time.sleep(0.5) if (time.time() - start) > timeout: self._proc.kill() self._stop_monitors()
class ManagedProcess(object): def __init__(self, cmdlineargs, env={}, umask=0o000, stdout_handler=None, stderr_handler=None): """ @brief Manages a long running process and passes stdout and stderr to handlers. @param cmdlineargs string or list of commandline arguments used to create the subprocess @param env Dict of environemnet variables set for the process @param umask Default permissions for files created byh this subprocess. Defaults to globally read and writeable! @param stdout_handler Handler for ouptut written to stdout @param stderr_handler Handler for ouptut written to stderr """ # cmdlineargs to list of strings if isinstance(cmdlineargs, str) or isinstance(cmdlineargs, unicode): cmdlineargs = cmdlineargs.split() cmdlineargs = map(str, cmdlineargs) self._cmdl = " ".join(cmdlineargs) def preexec_fn(): os.umask(umask) environ = os.environ.copy() environ.update(env) self._proc = Popen(cmdlineargs, stdout=PIPE, stderr=PIPE, shell=False, env=environ, close_fds=True, preexec_fn=preexec_fn) log.debug("Running command %s as pid %i", self._cmdl, self._proc.pid) if stdout_handler: self._stdout_handler = stdout_handler else: self._stdout_handler = lambda line: log.debug(self._cmdl + ":\n " + line.strip()) if stderr_handler: self._stderr_handler = stderr_handler else: self._stderr_handler = lambda line: log.error(self._cmdl + ":\n " + line.strip()) self.stdout_monitor = None self.stderr_monitor = None self.eop_monitor = None self._start_monitors() @property def pid(self): return self._proc.pid @property def returncode(self): return self._proc.returncode def is_alive(self): return self._proc.poll() is None def _start_monitors(self): self.stdout_monitor = PipeMonitor(self._proc.stdout, self._stdout_handler) self.stdout_monitor.start() self.stderr_monitor = PipeMonitor(self._proc.stderr, self._stderr_handler) self.stderr_monitor.start() def _stop_monitors(self): if self.stdout_monitor is not None: self.stdout_monitor.stop() self.stdout_monitor.join(3) self.stdout_monitor = None if self.stderr_monitor is not None: self.stderr_monitor.stop() self.stderr_monitor.join(3) self.stderr_monitor = None def terminate(self, timeout=5): start = time.time() self._stop_monitors() log.debug("Trying to terminate process {} ...".format(self._cmdl)) if self._proc is None: log.warning(" process already terminated!".format()) return while self._proc.poll() is None: time.sleep(0.5) if (time.time() - start) > timeout: log.debug("Reached timeout - Killing process") self._proc.kill() break self._proc = None # delete to avoid zombie process
class DbMonitor(object): """ @brief Monitor a dada buffer using dada_dbmonitor """ def __init__(self, key, callback=None): """ @ brief Constructor @param key key of dadabuffer to monitor @param callback Function to pass monitor info to. @detail Callback receives dict containing parsed output of dada_dbmonitor """ self._key = key self._dbmon_proc = None self._mon_thread = None self._callback = callback self.__parsed_lines = 0 self.__headersize = 12 # Skip first 12 lines def _stdout_parser(self, line): """ @brief Parse a line of output of the subprocess. """ self.__parsed_lines += 1 if self.__parsed_lines < self.__headersize: return None line = line.strip() try: values = map(int, line.split()) free, full, clear, written, read = values[5:] fraction = float(full) / (full + free) params = { "key": self._key, "fraction-full": fraction, "written": written, "read": read } except Exception as error: log.warning("Unable to parse line {} with error".format( line, str(error))) return None if self._callback is not None: self._callback(params) def start(self): """ @brief Start the monitor subprocess """ self._dbmon_proc = Popen(["dada_dbmonitor", "-k", self._key], stdout=PIPE, stderr=PIPE, shell=False, close_fds=True) self._mon_thread = PipeMonitor(self._dbmon_proc.stderr, self._stdout_parser) self._mon_thread.start() def stop(self): """ @brief Stop the monitor subprocess """ log.debug("Stopping monitor thread for dada buffer: {}".format( self._key)) self._dbmon_proc.terminate() self._mon_thread.stop() self._mon_thread.join(3) if self._dbmon_proc.returncode is None: log.warning( "Monitor thread for dada buffer: {} not terminated - killing it now!" .format(self._key)) self._dbmon_proc.kill() self._dbmon_proc = None # delete to avoid zombie process
def __init__(self, *args, **kwargs): PipeMonitor.__init__(self, *args, **kwargs) self.message_interval = 1.0 self.last_message_time = 0.0