def _stop_unix(self, errors): """ UNIX implementation of process killing @param errors: error messages. stop() will record messages into this list. @type errors: [str] """ self.exit_code = self.popen.poll() if self.exit_code is not None: logger.debug("process[%s].stop(): process has already returned %s", self.name, self.exit_code) #print "process[%s].stop(): process has already returned %s"%(self.name, self.exit_code) self.popen = None self.stopped = True return pid = self.popen.pid pgid = os.getpgid(pid) logger.info("process[%s]: killing os process with pid[%s] pgid[%s]", self.name, pid, pgid) try: # Start with SIGINT and escalate from there. logger.info("[%s] sending SIGINT to pgid [%s]", self.name, pgid) os.killpg(pgid, signal.SIGINT) logger.info("[%s] sent SIGINT to pgid [%s]", self.name, pgid) timeout_t = time.time() + _TIMEOUT_SIGINT retcode = self.popen.poll() while time.time() < timeout_t and retcode is None: time.sleep(0.1) retcode = self.popen.poll() # Escalate non-responsive process if retcode is None: printerrlog("[%s] escalating to SIGTERM"%self.name) timeout_t = time.time() + _TIMEOUT_SIGTERM os.killpg(pgid, signal.SIGTERM) logger.info("[%s] sent SIGTERM to pgid [%s]"%(self.name, pgid)) retcode = self.popen.poll() while time.time() < timeout_t and retcode is None: time.sleep(0.2) logger.debug('poll for retcode') retcode = self.popen.poll() if retcode is None: printerrlog("[%s] escalating to SIGKILL"%self.name) errors.append("process[%s, pid %s]: required SIGKILL. May still be running."%(self.name, pid)) try: os.killpg(pgid, signal.SIGKILL) logger.info("[%s] sent SIGKILL to pgid [%s]"%(self.name, pgid)) # #2096: don't block on SIGKILL, because this results in more orphaned processes overall #self.popen.wait() #os.wait() logger.info("process[%s]: sent SIGKILL", self.name) except OSError as e: if e.args[0] == 3: printerrlog("no [%s] process with pid [%s]"%(self.name, pid)) else: printerrlog("errors shutting down [%s], see log for details"%self.name) logger.error(traceback.format_exc()) else: logger.info("process[%s]: SIGTERM killed with return value %s", self.name, retcode) else: logger.info("process[%s]: SIGINT killed with return value %s", self.name, retcode) finally: self.popen = None
参考: