为什么ctrl + c不能停止龙卷风服务器?

时间:2017-06-26 13:25:43

标签: tornado

为什么 ctrl + c 不能在Windows上停止龙卷风服务器?

此代码未执行:print 'get sig:%d' % signum

import signal

import tornado
import tornado.web
import tornado.httpserver


class DefaultHandler(tornado.web.RequestHandler):

    def get(self):
        self.set_status(200, 'OK')
        self.write('hello guest')

    def post(self):
        self.get()


class Receiver(object):

    def __init__(self, address=None, port=8100, gzip=False):

        if not address:
            address = '0.0.0.0'
        self.address = address
        self.port = port
        self.gzip = gzip
        self.http_server = None

    def start(self):
        settings = dict(
        )
        application = tornado.web.Application([
            (r"/", DefaultHandler),],
            **settings)
        self.http_server = tornado.httpserver.HTTPServer(application, decompress_request=self.gzip)
        self.http_server.listen(self.port)
        tornado.ioloop.IOLoop.instance().start()

    def shutdown(self):

        if self.http_server is not None:
            self.http_server.stop()
        tornado.ioloop.IOLoop.instance().stop()


if __name__ == '__main__':
    receiver = Receiver(port=8901)

    def sig_handler(signum, frame):
        print 'get sig:%d' % signum
        receiver.shutdown()


    signal.signal(signal.SIGTERM, sig_handler)
    signal.signal(signal.SIGINT, sig_handler)
    receiver.start()

我的解决方案:

只有主线程可以处理信号,所以使用线程启动接收器并让主线程做一些假工作来保持活动

threading.Thread(target=receiver.start).start()
while 1:
    try:
        time.sleep(2)
    except:
        break

2 个答案:

答案 0 :(得分:2)

信号处理程序是一种特殊的环境。你必须小心你在一个人做什么,因为你不知道被信号中断的功能的状态。在龙卷风中,只保证一个函数可以安全地从信号处理程序内部调用:IOLoop.add_callback_from_signal。不要直接调用shutdown(),而是使用add_callback_from_signal来安排它:

def sig_handler(signum, frame):
    IOLoop.current().add_callback_from_signal(receiver.shutdown)

答案 1 :(得分:0)

我在这里写了更详细的答案:https://stackoverflow.com/a/52941752/207661

简而言之,您需要为Windows手动安装Ctrl + C处理程序。

以下是方便的功能,这些功能将检测Windows并在控制台中安装Ctrl + C的自定义处理程序:

#win_ctrl_c.py

import sys

def handler(a,b=None):
    sys.exit(1)
def install_handler():
    if sys.platform == "win32":
        import win32api
        win32api.SetConsoleCtrlHandler(handler, True)

您可以在上面这样使用:

import threading
import time
import win_ctrl_c

# do something that will block
def work():
    time.sleep(10000)        
t = threading.Thread(target=work)
t.daemon = True
t.start()

#install handler
install_handler()

# now block
t.join()

#Ctrl+C works now!