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
参考:http://wiki.ros.org/roslaunch