def exited(self, status): # Log last output for line in self.readlines(): pass # Display exit code if status is not None: log_func = self.warning info = [] if WCOREDUMP(status): info.append("core.%s dumped!" % self._pid) log_func = self.error if WIFSIGNALED(status): signal = WTERMSIG(status) signal = SIGNAME.get(signal, signal) info.append("signal %s" % signal) if WIFEXITED(status): info.append("exitcode=%s" % WEXITSTATUS(status)) if info: log_func("Exit (%s)" % ", ".join(info)) else: log_func("Exit") else: self.error("Process exited (ECHILD error)") # Delete process self.process = None self._pid = None
def _debug_event_iteration(self): # (pid, status) = waitpid(self.pid, 0) (pid, status) = waitpid(0, 0) self.pid = pid signum = 0 logger.debug('status:' + hex(status) + ' pid:' + str(pid)) # Process exited? if WIFEXITED(status): self._event_handle_process_exit(status, pid) # Process killed by a signal? elif WIFSIGNALED(status): self._event_handle_process_kill(status, pid) # Invalid process status? elif not WIFSTOPPED(status): self._event_handle_process_unknown_status(status, pid) # Ptrace event? elif self.WPTRACEEVENT(status): self._event_handle_process_ptrace_event(status, pid) else: signum = self._event_handle_process_signal(status, pid) # continue if signum is None: signum = 0 if self.single_step_flag | (self._restore_breakpoint is not None): self._ptrace(PTRACE_SINGLESTEP, pid, 0, signum) elif self.trace_sys_call_flag: self._ptrace(PTRACE_SYSCALL, pid, 0, signum) else: self._ptrace(PTRACE_CONT, pid, 0, signum)
def execute(self, *args): process = Popen4([self.facility.path] + self.facility.args + list(args)) timers = [ Timer(time, self.kill, [process.pid, signal]) for time, signal in self.facility.wait.iteritems() ] for timer in timers: timer.start() status = process.wait() for timer in timers: # No penalty, btw, for cancelling a dead timer if timer.isAlive(): timer.cancel() process.tochild.close() if __debug__: while True: line = process.fromchild.readline() if line: syslog(line) else: break process.fromchild.close() command = basename(self.facility.path) if WIFEXITED(status): exit_status = WEXITSTATUS(status) if exit_status != EX_OK: raise ExecutionError( EX_SOFTWARE, '`%(command)s\' exited with \ error-code %(exit_status)d' % { 'command': command, 'exit_status': exit_status }) elif WIFSIGNALED(status): raise ExecutionError( EX_SOFTWARE, '`%(command)s\' terminated \ with signal %(signal)d' % { 'command': command, 'signal': WTERMSIG(status) }) elif WIFSTOPPED(status): raise ExecutionError( EX_SOFTWARE, '`%(command)s\' stopped with \ signal %(signal)d' % { 'command': command, 'signal': WSTOPSIG(status) }) else: # Failsafe: timers should have killed the process by this point, or # it should have ended naturally. kill(process.pid, SIGKILL) raise ExecutionError( EX_SOFTWARE, 'Failed timer on `%(command)s\'; \ terminating the process extraordinarily.' % {'command': command})
def formatProcessStatus(status, title="Process"): if WIFSTOPPED(status): signum = WSTOPSIG(status) return "%s stopped by signal %s" % (title, signalName(signum)) if WIFSIGNALED(status): signum = WTERMSIG(status) return "%s killed by signal %s" % (title, signalName(signum)) if not WIFEXITED(status): raise ValueError("Invalid status: %r" % status) exitcode = WEXITSTATUS(status) if exitcode: return "%s exited with code %s" % (title, exitcode) else: return "%s exited normally" % title
def parent_execute(self): # 忽略信号。 map(lambda s: signal(s, SIG_IGN), (SIGINT, SIGUSR2)) # 向子进程广播 INT 信号。 signal(SIGTERM, lambda *args: killpg(getpid(), SIGINT)) # 增加子进程。 signal(SIGUSR1, lambda *args: self.fork_workers(1)) # 等待所有子进程退出。 while True: try: _, status = wait() # 如果子进程非正常退出,新建。 (not WIFEXITED(status)) and self.fork_workers(1) except OSError as ex: # 没有其他子进程,退出。 if ex.errno == ECHILD: break
def _waitpid(pid): """Convenience wrapper around the original waitpid invocation.""" # 0 and -1 trigger a different behavior in waitpid. We disallow those # values. assert pid > 0 while True: pid_, status = waitpid_(pid, 0) assert pid_ == pid if WIFEXITED(status): return WEXITSTATUS(status) elif WIFSIGNALED(status): # Signals are usually represented as the negated signal number. return -WTERMSIG(status) elif WIFSTOPPED(status) or WIFCONTINUED(status): # In our current usage scenarios we can simply ignore SIGSTOP and # SIGCONT by restarting the wait. continue else: assert False return 1
def formatProcessStatus(status, title="Process"): """ Format a process status (integer) as a string. """ if WIFSTOPPED(status): signum = WSTOPSIG(status) text = "%s stopped by signal %s" % (title, signalName(signum)) elif WIFSIGNALED(status): signum = WTERMSIG(status) text = "%s killed by signal %s" % (title, signalName(signum)) else: if not WIFEXITED(status): raise ValueError("Invalid status: %r" % status) exitcode = WEXITSTATUS(status) if exitcode: text = "%s exited with code %s" % (title, exitcode) else: text = "%s exited normally" % title if WCOREDUMP(status): text += " (core dumped)" return text
def __init__(self, command, fc=True): ''' Creates object _and_ runs a command command - a command to run fc - `fast call` - whether to run via fork'n'exec (True) or in the subshell (False) ''' if fc: command = command.split() inst = Popen3(command, True, -1) (o, i, e) = (inst.fromchild, inst.tochild, inst.childerr) self.pid = inst.pid self.elines = e.readlines() self.lines = o.readlines() ret = inst.wait() if WIFEXITED(ret): self.ret = WEXITSTATUS(ret) else: self.ret = 255 i.close() o.close() e.close() self.edata = "" self.data = "" for i in self.lines: self.data += i for i in self.elines: self.edata += i
def processStatus(self, status): # Process exited? if WIFEXITED(status): code = WEXITSTATUS(status) event = self.processExited(code) # Process killed by a signal? elif WIFSIGNALED(status): signum = WTERMSIG(status) event = self.processKilled(signum) # Invalid process status? elif not WIFSTOPPED(status): raise ProcessError(self, "Unknown process status: %r" % status) # Ptrace event? elif HAS_PTRACE_EVENTS and WPTRACEEVENT(status): event = WPTRACEEVENT(status) event = self.ptraceEvent(event) else: signum = WSTOPSIG(status) event = self.processSignal(signum) return event
#