Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def on_event_in_sequence(self, process, jobs):
""" Manages the impact of an event that is part of the starting sequence. """
if process.state in [ProcessStates.STOPPED, ProcessStates.STOPPING, ProcessStates.UNKNOWN]:
# unexpected event in a starting phase: someone has requested to stop the process as it is starting
# remove from inProgress
process.ignore_wait_exit = False
jobs.remove(process)
# decide to continue starting or not
self.process_failure(process)
elif process.state == ProcessStates.STARTING:
# on the way
pass
elif process.state == ProcessStates.RUNNING:
# if not exit expected, job done. otherwise, wait
if not process.rules.wait_exit or process.ignore_wait_exit:
process.ignore_wait_exit = False
jobs.remove(process)
elif process.state == ProcessStates.BACKOFF:
# something wrong happened, just wait
def _restart_process(self, process_spec):
"""Restart a process.
"""
name_spec = make_namespec(
process_spec[GROUP_KEY], process_spec[NAME_KEY])
rpc_client = childutils.getRPCInterface(self._environment)
process_spec = rpc_client.supervisor.getProcessInfo(name_spec)
if process_spec[STATE_KEY] is ProcessStates.RUNNING:
self._log('Trying to stop process %s', name_spec)
try:
rpc_client.supervisor.stopProcess(name_spec)
self._log('Stopped process %s', name_spec)
except xmlrpclib.Fault as exc:
self._log('Failed to stop process %s: %s', name_spec, exc)
try:
self._log('Starting process %s', name_spec)
rpc_client.supervisor.startProcess(name_spec, False)
except xmlrpclib.Fault as exc:
self._log('Failed to start process %s: %s', name_spec, exc)
else:
self._log('%s not in RUNNING state, cannot restart', name_spec)
# circular import problems.
class ProcessStates:
STOPPED = 0
STARTING = 10
RUNNING = 20
BACKOFF = 30
STOPPING = 40
EXITED = 100
FATAL = 200
UNKNOWN = 1000
STOPPED_STATES = (ProcessStates.STOPPED,
ProcessStates.EXITED,
ProcessStates.FATAL,
ProcessStates.UNKNOWN)
RUNNING_STATES = (ProcessStates.RUNNING,
ProcessStates.BACKOFF,
ProcessStates.STARTING)
def getProcessStateDescription(code):
return _process_states_by_code.get(code)
class SupervisorStates:
FATAL = 2
RUNNING = 1
RESTARTING = 0
SHUTDOWN = -1
def getSupervisorStateDescription(code):
if state == ProcessStates.RUNNING:
start = info['start']
now = info['now']
start_dt = datetime.datetime(*time.gmtime(start)[:6])
now_dt = datetime.datetime(*time.gmtime(now)[:6])
uptime = now_dt - start_dt
if _total_seconds(uptime) < 0: # system time set back
uptime = datetime.timedelta(0)
desc = 'pid %s, uptime %s' % (info['pid'], uptime)
elif state in (ProcessStates.FATAL, ProcessStates.BACKOFF):
desc = info['spawnerr']
if not desc:
desc = 'unknown error (try "tail %s")' % info['name']
elif state in (ProcessStates.STOPPED, ProcessStates.EXITED):
if info['start']:
stop = info['stop']
stop_dt = datetime.datetime(*time.localtime(stop)[:7])
desc = stop_dt.strftime('%b %d %I:%M %p')
else:
desc = 'Not started'
else:
desc = ''
return desc
def force_process_unknown(self, namespec, reason):
""" This method forces the UNKNOWN process state into Supervisor internal data
and dispatches process event to event listeners. """
process = self.get_process(namespec)
process.spawnerr = reason
process.change_state(ProcessStates.UNKNOWN)
if st is None:
filename = program
else:
filename = found
# check_execv_args will raise a ProcessException if the execv
# args are bogus, we break it out into a separate options
# method call here only to service unit tests
self.config.options.check_execv_args(filename, commandargs, st)
return filename, commandargs
event_map = {
ProcessStates.BACKOFF: events.ProcessStateBackoffEvent,
ProcessStates.FATAL: events.ProcessStateFatalEvent,
ProcessStates.UNKNOWN: events.ProcessStateUnknownEvent,
ProcessStates.STOPPED: events.ProcessStateStoppedEvent,
ProcessStates.EXITED: events.ProcessStateExitedEvent,
ProcessStates.RUNNING: events.ProcessStateRunningEvent,
ProcessStates.STARTING: events.ProcessStateStartingEvent,
ProcessStates.STOPPING: events.ProcessStateStoppingEvent,
}
def change_state(self, new_state, expected=True):
old_state = self.state
if new_state is old_state:
# exists for unit tests
return False
event_class = self.event_map.get(new_state)
if event_class is not None:
event = event_class(self, old_state, expected)
as_group = "process group "
options.logger.debug('killing %s (pid %s) %swith signal %s'
% (self.config.name,
self.pid,
as_group,
signame(sig))
)
# RUNNING/STARTING/STOPPING -> STOPPING
self.killing = 1
self.delay = now + self.config.stopwaitsecs
# we will already be in the STOPPING state if we're doing a
# SIGKILL as a result of overrunning stopwaitsecs
self._assertInState(ProcessStates.RUNNING,ProcessStates.STARTING,
ProcessStates.STOPPING)
self.change_state(ProcessStates.STOPPING)
pid = self.pid
if killasgroup:
# send to the whole process group instead
pid = -self.pid
try:
options.kill(pid, sig)
except:
io = StringIO.StringIO()
traceback.print_exc(file=io)
tb = io.getvalue()
msg = 'unknown problem killing %s (%s):%s' % (self.config.name,
self.pid, tb)
options.logger.critical(msg)
self.laststop = now
processname = self.config.name
tooquickly = now - self.laststart < self.config.startsecs
exit_expected = es in self.config.exitcodes
if self.killing:
# likely the result of a stop request
# implies STOPPING -> STOPPED
self.killing = 0
self.delay = 0
self.exitstatus = es
msg = "stopped: %s (%s)" % (processname, msg)
self._assertInState(ProcessStates.STOPPING)
self.change_state(ProcessStates.STOPPED)
elif tooquickly:
# the program did not stay up long enough to make it to RUNNING
# implies STARTING -> BACKOFF
self.exitstatus = None
self.spawnerr = 'Exited too quickly (process log may have details)'
msg = "exited: %s (%s)" % (processname, msg + "; not expected")
self._assertInState(ProcessStates.STARTING)
self.change_state(ProcessStates.BACKOFF)
else:
# this finish was not the result of a stop request, the
# program was in the RUNNING state but exited implies
# RUNNING -> EXITED
self.delay = 0
self.backoff = 0
# we use a list here to fake out lexical scoping;
# using a direct assignment to 'started' in the
# function appears to not work (symptom: 2nd or 3rd
# call through, it forgets about 'started', claiming
# it's undeclared).
started.append(time.time())
if not wait or not startsecs:
return True
t = time.time()
runtime = (t - started[0])
state = process.get_state()
if state not in (ProcessStates.STARTING, ProcessStates.RUNNING):
raise RPCError(Faults.ABNORMAL_TERMINATION, name)
if runtime < startsecs:
return NOT_DONE_YET
if state == ProcessStates.RUNNING:
return True
raise RPCError(Faults.ABNORMAL_TERMINATION, name)
options = self.config.options
if self.pid:
msg = 'process %r already running' % self.config.name
options.logger.warn(msg)
return
self.killing = 0
self.spawnerr = None
self.exitstatus = None
self.system_stop = 0
self.administrative_stop = 0
self.laststart = time.time()
self._assertInState(ProcessStates.EXITED, ProcessStates.FATAL,
ProcessStates.BACKOFF, ProcessStates.STOPPED)
self.change_state(ProcessStates.STARTING)
try:
filename, argv = self.get_execv_args()
except ProcessException, what:
self.record_spawnerr(what.args[0])
self._assertInState(ProcessStates.STARTING)
self.change_state(ProcessStates.BACKOFF)
return
try:
self.dispatchers, self.pipes = self.config.make_dispatchers(self)
except OSError, why:
code = why[0]