def __init__(self, name, command, params=None, workdir=None, host=None, allowTerminate=False): if host == None: host = CRemoteHostInfo() CProcessBase.__init__(self, name, host) CLogMessageSource.__init__(self) self.command = command self.params = params # Configurable parameters self.workdir = workdir self.process = None self.lastPollState = 0 self.keepalive = False self.allowTerminate = allowTerminate # CAST apps should not autoTerm; others may self.restarted = 0 self.willClearAt = None # Flushing self.pipeReader = None self.partialLine = {} # one place for every pipe self.srcid = "process.%s.%s" % (self.host.host.replace('.', '_'), self.name.replace('.', '_')) self.messageQueue = CMessageTextQueue(self.srcid)
class CProcess(CProcessBase, CLogMessageSource): def __init__(self, name, command, params=None, workdir=None, host=None, allowTerminate=False): if host == None: host = CRemoteHostInfo() CProcessBase.__init__(self, name, host) CLogMessageSource.__init__(self) self.command = command self.params = params # Configurable parameters self.workdir = workdir self.process = None self.lastPollState = 0 self.keepalive = False self.allowTerminate = allowTerminate # CAST apps should not autoTerm; others may self.restarted = 0 self.willClearAt = None # Flushing self.pipeReader = None self.partialLine = {} # one place for every pipe self.srcid = "process.%s.%s" % (self.host.host.replace('.', '_'), self.name.replace('.', '_')) self.messageQueue = CMessageTextQueue(self.srcid) def __del__(self): self.stop() def _getLogMessages(self): # CLogMessageSource return self.messageQueue.getMessages(True, True) def isSameLogMessageSource(self, aObject): #CLogMessageSource return aObject == self def setMessageProcessor(self, messageProcessor): # CLogMessageSource self.messageQueue.messageProcessor = messageProcessor def getStatusStr(self): st = CProcessBase.getStatusStr(self) if st != None: return st if self.process == None: return "Not started" if self.restarted > 0: return "%d (r%d)" % (self.process.pid, self.restarted) return "%d" % self.process.pid def isRunning(self): if self.process == None: return False self.lastPollState = self.process.poll() if self.lastPollState == None: return True return False def _setStatus(self, newStatus): old = self.status self.status = newStatus self.notifyStatusChange(old, newStatus) def _beginFlush(self): self.willClearAt = time.time() + 1 self._setStatus(CProcessBase.FLUSH) def start(self, command=None, params=None, workdir=None, env=None, allowTerminate=None): if self.isRunning(): warn("Process '%s' is already running" % self.name) return if params == None: params = self.params else: self.params = params if command == None or command.strip() == "": if self.command == None or self.command.strip() == "": error("No command for process '%s'" % self.name) return command = self.command self.error = CProcessBase.OK if params != None: for par in params.iterkeys(): command = command.replace("[%s]" % par, "%s" % params[par]) log("CMD=%s" % command) command = cmdlineToArray(command) if workdir == None or workdir.strip() == "": workdir = self.workdir if workdir != None: log("PWD=%s" % workdir) if allowTerminate != None: self.allowTerminate = True if allowTerminate else False try: self._setStatus(CProcessBase.STARTING) self._startReader() self.process = subp.Popen( command, bufsize=1, stdout=subp.PIPE, stderr=subp.PIPE, cwd=workdir, env=env) # Make the pipes nonblocking so we can read the messages better fcntl.fcntl(self.process.stdout, fcntl.F_SETFL, os.O_NONBLOCK) fcntl.fcntl(self.process.stderr, fcntl.F_SETFL, os.O_NONBLOCK) time.sleep(0.01) self._setStatus(max(1, self.process.pid)) log("Process '%s' started, pid=%d" % (self.name, self.process.pid)) except Exception, e: self.process = None self.error = CProcessBase.ERRSTART self._setStatus(CProcessBase.STOPPED) error("Process '%s' failed to start" % (self.name)) error("Command: '%s'" % (" ".join(command))) error("%s" % e) time.sleep(0.01)