Why does ctrl + c not stop tornado server?

浪尽此生 提交于 2019-12-24 09:29:18

问题


Why does ctrl + c not stop tornado server on windows ?

This code is not executed: 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()

My solution:

only main thread can handle signal, so use thread to start receiver and let main thread do some fake work to keep alive

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

回答1:


Signal handlers are a special environment. You have to be careful what you do in one because you don't know the state of the functions that were interrupted by the signal. In tornado, only one function is guaranteed safe to call from inside a signal handler: IOLoop.add_callback_from_signal. Instead of calling shutdown() directly, use add_callback_from_signal to schedule it:

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



回答2:


I wrote the more detailed answer here: https://stackoverflow.com/a/52941752/207661

In short, you need to install Ctrl+C handler for Windows manually.

Below are handy functions which will detect Windows and install custom handler for Ctrl+C in console:

#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)

You can use above like this:

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!


来源:https://stackoverflow.com/questions/44760845/why-does-ctrl-c-not-stop-tornado-server

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!