2011-10-12 20 views
6

Estoy comenzando con DBus y la programación impulsada por eventos en general. El servicio que estoy tratando de crear realmente consta de tres partes, pero dos son realmente cosas de "servidor".Dbus/GLib Main Loop, Background Thread

1) El servidor DBus real habla con un sitio web remoto a través de HTTPS, gestiona las sesiones y transmite información a los clientes.

2) La otra parte del servicio de llamadas de una página viva mantener cada 2 minutos para mantener la sesión activa en el sitio web externo

3) Los clientes hacen llamadas al servicio para recuperar información del servicio.

Encontré algunos programas de ejemplo simples. Intento adaptarlos al prototipo n. ° 1 y n. ° 2. En lugar de crear programas separados para ambos. Pensé que podía ejecutarlos en un solo proceso de dos hilos.

El problema que estoy viendo es que llamo time.sleep (X) en mi hilo keep alive. El hilo se va a dormir, pero nunca se despertará. Creo que el GIL no es liberado por el bucle principal de GLib.

Aquí está mi código de hilo:

class Keepalive(threading.Thread): 
    def __init__(self, interval=60): 
    super(Keepalive, self).__init__() 
    self.interval = interval 
    bus = dbus.SessionBus() 
    self.remote = bus.get_object("com.example.SampleService", "/SomeObject") 

    def run(self): 
    while True: 
     print('sleep %i' % self.interval) 
     time.sleep(self.interval) 
     print('sleep done') 
     reply_status = self.remote.keepalive() 
     if reply_status: 
      print('Keepalive: Success') 
     else: 
      print('Keepalive: Failure') 

De las declaraciones de impresión, sé que el sueño comienza, pero nunca veo "sueño hecho".

Este es el código principal:

if __name__ == '__main__': 
try: 
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 

    session_bus = dbus.SessionBus() 
    name = dbus.service.BusName("com.example.SampleService", session_bus) 
    object = SomeObject(session_bus, '/SomeObject') 

    mainloop = gobject.MainLoop() 

    ka = Keepalive(15) 
    ka.start() 
    print('Begin main loop') 
    mainloop.run() 
except Exception as e: 
    print(e) 
finally: 
    ka.join() 

Algunas otras observaciones:

veo el mensaje "comenzará bucle principal", por lo que sabe que es conseguir el control. Luego, veo "sleep% i", y después de eso, nada.

Si I^C, entonces veo "dormir hecho". Después de unos 20 segundos, consigo una excepción a self.run() que la aplicación remota no respondió:

DBusException: org.freedesktop.DBus.Error.NoReply: no recibió una respuesta. Las posibles causas incluyen: la aplicación remota no envió una respuesta, la política de seguridad del bus de mensajes bloqueó la respuesta, el tiempo de espera de respuesta expiró o la conexión de red se interrumpió.

¿Cuál es la mejor manera de ejecutar mi código keep alive dentro del servidor?

Gracias,

Respuesta

6

Debe permitir explícitamente al utilizar múltiples hilos gobject llamando gobject.threads_init(). Consulte el PyGTK FAQ para obtener información de fondo.

Además de eso, para el propósito que describes, los tiempos de espera parecen ajustarse mejor. Utilice la siguiente manera:

# Enable timer 
self.timer = gobject.timeout_add(time_in_ms, self.remote.keepalive) 
# Disable timer 
gobject.source_remove(self.timer) 

Este llama a la función keepalive cada time_in_ms (mili) segundos. Más detalles, de nuevo, se pueden encontrar en el PyGTK reference.

+0

Jro, Gracias por la sugerencia. Soy nuevo en esto y realmente no entendí la relación entre dbus/glib/gtk/gobject. tomeout_add() es exactamente lo que quiero. – fandingo