昨天写了一个简单的游戏服务器,在终端启动的时候,奇了个怪了,按CTRL+C,无法把进程停下来,当再次启动时报
CannotListenError: Couldn't listen on any:2404: [Errno 98] Address already in use.错误,查了一下,原来在python中,非主线程不能处理信号,而twisted中epollreactor.EpollReactor接受CTRL+C信号只是把当时的主线程的reactor停下来,其它线程的reactor并没有停下来。既然这样,注册一个CTRL+C信号处理,在处理函数把其它线程的reactor一个一个的停下来。上网百度,找了半天,都没有跟python twisted信号处理有关的资料,只好去看源码,发现有这么一段
class _SignalReactorMixin:
"""
Private mixin to manage signals: it installs signal handlers at start time,
and define run method.
It can only be used mixed in with L{ReactorBase}, and has to be defined
first in the inheritance (so that method resolution order finds
startRunning first).
@type _installSignalHandlers: C{bool}
@ivar _installSignalHandlers: A flag which indicates whether any signal
handlers will be installed during startup. This includes handlers for
SIGCHLD to monitor child processes, and SIGINT, SIGTERM, and SIGBREAK
to stop the reactor.
"""
_installSignalHandlers = False
def _handleSignals(self):
"""
Install the signal handlers for the Twisted event loop.
"""
try:
import signal
except ImportError:
log.msg("Warning: signal module unavailable -- "
"not installing signal handlers.")
return
if signal.getsignal(signal.SIGINT) == signal.default_int_handler:
# only handle if there isn't already a handler, e.g. for Pdb.
signal.signal(signal.SIGINT, self.sigInt)
signal.signal(signal.SIGTERM, self.sigTerm)
# Catch Ctrl-Break in windows
if hasattr(signal, "SIGBREAK"):
signal.signal(signal.SIGBREAK, self.sigBreak)
if platformType == 'posix':
signal.signal(signal.SIGCHLD, self._handleSigchld)
sigInt然后把写一个类,继承于EpollReactor,重写sigInt函数
class MainReactor(epollreactor.EPollReactor):
def __init__(self):
epollreactor.EPollReactor.__init__(self)
self.monitors = []
def sigInt(self, *args):
print "sigInt"
self.stop_all_reactor()
# epollreactor.EPollReactor.sigInt(self,args)
def add_monitor(self,monitor):
self.monitors.append(monitor)
def stop_all_reactor(self):
for monitor in self.monitors:
monitor.stop()
self.stop()
这样主线程的reactor接受到CTRL+C信号时,在sigInt里面把所有线程的reactor停下来。