2009-07-02 12 views
7

Tengo una aplicación que ejecuta Twisted iniciando el reactor con reactor.run() en mi hilo principal después de iniciar algunos otros hilos, incluido el servidor web CherryPy. Aquí hay un programa que se cierra limpiamente cuando se pulsa Ctrl + C en Linux, pero no en Windows:CherryPy interfiere con el apagado torcido en 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() 

Creo que CherryPy es el culpable aquí, porque aquí hay un programa diferente que escribí sin CherryPy que hace apagado limpiamente tanto en Linux y Windows, cuando se pulsa Ctrl + C:

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

¿alguien tiene alguna idea de lo que es el problema? Aquí está mi dilema:

  • En Linux todo funciona
  • En Windows, puedo llamar a las funciones de los gestores de señales usando reactor.callFromThread cuando CherryPy no se está ejecutando
  • Cuando CherryPy se está ejecutando, ninguna función que llamar usando reactor.callFromThread de un controlador de señal alguna vez se ejecutará (he verificado que el manejador de señal sí se llama)

¿Qué puedo hacer al respecto? ¿Cómo puedo cerrar Twisted en Windows desde un controlador de señal mientras ejecuto CherryPy? ¿Es esto un error, o simplemente me he perdido una parte importante de la documentación de cualquiera de estos dos proyectos?

Respuesta

14

CherryPy maneja las señales de manera predeterminada cuando llamas a inicio rápido. En su caso, probablemente debería desenrollar el inicio rápido, que es solo unas pocas líneas, y seleccionar y elegir. Aquí está, básicamente, lo que hace de inicio rápido en el maletero:

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

En su caso, usted no necesita los manejadores de señales, por lo que se puede omitir aquellos. Tampoco es necesario que invoque engine.block si no está iniciando CherryPy desde el hilo principal. Engine.block() es solo una forma de hacer que el hilo principal no termine inmediatamente, sino que espere la finalización del proceso (esto es para que la autorecarga funcione de manera confiable, algunas plataformas tienen problemas para llamar a execv desde cualquier hilo, excepto el hilo principal).

Si elimina la llamada block(), ni siquiera necesita el Thread() alrededor del inicio rápido. Por lo tanto, reemplazar su línea:

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

con:

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

Gracias tanto! Su respuesta fue tan bien escrita y útil que comencé una recompensa solo para darle 50 reputación. –

Cuestiones relacionadas