CherryPy会干扰Twisted在Windows上的关闭 [英] CherryPy interferes with Twisted shutting down on Windows

查看:61
本文介绍了CherryPy会干扰Twisted在Windows上的关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行Twisted的应用程序,它是在启动了其他一些线程(包括CherryPy Web服务器)之后,通过在主线程中使用 reactor.run()来启动反应堆的.这是一个在Linux而非Windows上按Ctrl + C会完全关闭的程序:

 来自线程导入线程从信号导入信号SIGINT导入cherrypy来自twist.internet进口反应堆从twisted.web.client导入getPagedef停止(信号,帧):cherrypy.engine.exit()Reactor.CallFromThread(reactor.stop)信号(SIGINT,停止)类根:@ cherrypy.exposedef索引(自己):Reactor.callFromThread(启动)返回"Hello World!"cherrypy.server.socket_host ="0.0.0.0"线程(target = cherrypy.quickstart,args = [Root()]).start()def print_page(html):打印(HTML)def kickoff():getPage("http://acpstats/account/login").addCallback(print_page)react.run() 

我相信CherryPy是这里的罪魁祸首,因为这是我写的没有CherryPy的另一个程序,当按下Ctrl + C时,它在Linux和Windows上都可以正常关机:

 从时间导入睡眠从线程导入线程从信号导入信号SIGINT来自twist.internet进口反应堆从twisted.web.client导入getPagekeep_going =真def停止(信号,帧):全球保持keep_going =假Reactor.CallFromThread(reactor.stop)信号(SIGINT,停止)def print_page(html):打印(HTML)def kickoff():getPage("http://acpstats/account/login").addCallback(print_page)defperiod_downloader():在keep_going时:Reactor.callFromThread(启动)睡眠(5)线程(target = periodic_downloader).start()react.run() 

有人知道这个问题是什么吗?这是我的难题:

  • 在Linux上一切正常
  • 在Windows上,当CherryPy未运行时,我可以使用 reactor.callFromThread 从信号处理程序中调用函数
  • CherryPy运行时,我使用信号处理程序中的 reactor.callFromThread 调用的函数将永远不会执行(我已确认信号处理程序本身确实会被调用)

对此我该怎么办?如何在运行CherryPy时从信号处理程序中关闭Twisted在Windows上?这是一个错误,还是我只是错过了这两个项目中任何一个的文档的重要部分?

解决方案

默认情况下,CherryPy在调用quickstart时会处理信号.在您的情况下,您应该只展开快速启动(仅几行),然后选择即可.基本上,这是快速入门在中继中的作用:

 如果配置:cherrypy.config.update(config)tree.mount(root,script_name,config)如果hasattr(engine,"signal_handler"):engine.signal_handler.subscribe()如果hasattr(engine,"console_control_handler"):engine.console_control_handler.subscribe()启动引擎()engine.block() 

在您的情况下,您不需要信号处理程序,因此可以将其省略.如果您不是从主线程启动CherryPy,也不需要调用engine.block.Engine.block()只是使主线程不立即终止的一种方法,而是等待进程终止(这是为了使autoreload可靠地工作;某些平台存在从主线程以外的任何线程调用execv的问题).

如果删除block()调用,则甚至不需要在quickstart周围使用Thread().因此,替换您的行:

  Thread(target = cherrypy.quickstart,args = [Root()]).start() 

具有:

  cherrypy.tree.mount(Root())cherrypy.engine.start() 

I've got an application that runs Twisted by starting the reactor with reactor.run() in my main thread after starting some other threads, including the CherryPy web server. Here's a program that shuts down cleanly when Ctrl+C is pressed on Linux but not on Windows:

from threading import Thread
from signal import signal, SIGINT

import cherrypy

from twisted.internet import reactor
from twisted.web.client import getPage

def stop(signum, frame):
    cherrypy.engine.exit()
    reactor.callFromThread(reactor.stop)
signal(SIGINT, stop)

class Root:
    @cherrypy.expose
    def index(self):
        reactor.callFromThread(kickoff)
        return "Hello World!"

cherrypy.server.socket_host = "0.0.0.0"
Thread(target=cherrypy.quickstart, args=[Root()]).start()

def print_page(html):
    print(html)

def kickoff():
    getPage("http://acpstats/account/login").addCallback(print_page)

reactor.run()

I believe that CherryPy is the culprit here, because here's a different program that I wrote without CherryPy that does shutdown cleanly on both Linux and Windows when Ctrl+C is pressed:

from time import sleep
from threading import Thread
from signal import signal, SIGINT

from twisted.internet import reactor
from twisted.web.client import getPage

keep_going = True
def stop(signum, frame):
    global keep_going
    keep_going = False
    reactor.callFromThread(reactor.stop)
signal(SIGINT, stop)

def print_page(html):
    print(html)

def kickoff():
    getPage("http://acpstats/account/login").addCallback(print_page)

def periodic_downloader():
    while keep_going:
        reactor.callFromThread(kickoff)
        sleep(5)

Thread(target=periodic_downloader).start()
reactor.run()

Does anyone have any idea what the problem is? Here's my conundrum:

  • On Linux everything works
  • On Windows, I can call functions from signal handlers using reactor.callFromThread when CherryPy is not running
  • When CherryPy is running, no function that I call using reactor.callFromThread from a signal handler will ever execute (I've verified that the signal handler itself does get called)

What can I do about this? How can I shut down Twisted on Windows from a signal handler while running CherryPy? Is this a bug, or have I simply missed some important part of the documentation for either of these two projects?

解决方案

CherryPy handles signals by default when you call quickstart. In your case, you should probably just unroll quickstart, which is only a few lines, and pick and choose. Here's basically what quickstart does in trunk:

if config:
    cherrypy.config.update(config)

tree.mount(root, script_name, config)

if hasattr(engine, "signal_handler"):
    engine.signal_handler.subscribe()
if hasattr(engine, "console_control_handler"):
    engine.console_control_handler.subscribe()

engine.start()
engine.block()

In your case, you don't need the signal handlers, so you can omit those. You also don't need to call engine.block if you're not starting CherryPy from the main thread. Engine.block() is just a way to make the main thread not terminate immediately, but instead wait around for process termination (this is so autoreload works reliably; some platforms have issues calling execv from any thread but the main thread).

If you remove the block() call, you don't even need the Thread() around quickstart. So, replace your line:

Thread(target=cherrypy.quickstart, args=[Root()]).start()

with:

cherrypy.tree.mount(Root())
cherrypy.engine.start()

这篇关于CherryPy会干扰Twisted在Windows上的关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆