2011-10-12 11 views
6

Inizio con DBus e programmazione guidata da eventi in generale. Il servizio che sto cercando di creare è composto da tre parti, ma due sono davvero cose "server".Anello principale Dbus/GLib, filettatura di fondo

1) L'attuale server DBus comunica con un sito Web remoto su HTTPS, gestisce le sessioni e trasmette informazioni ai client.

2) L'altra parte del servizio chiama una pagina di tenere viva ogni 2 minuti per mantenere attiva la sessione sul sito web esterno

3) I clienti fanno chiamate al servizio per recuperare informazioni dal servizio.

Ho trovato alcuni semplici programmi di esempio. Sto cercando di adattarli al prototipo # 1 e # 2. Piuttosto che costruire programmi separati per entrambi. Ho pensato di poterli eseguire in un singolo processo a due thread.

Il problema che sto vedendo è che chiamo time.sleep (X) nel mio thread keep alive. Il thread va a dormire, ma non si sveglierà mai. Penso che GIL non sia rilasciato dal ciclo principale di GLib.

Ecco il mio codice discussione:

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

Dalle dichiarazioni di stampa, lo so che il sonno inizia, ma non ho mai visto "sonno fatto".

Ecco il codice principale:

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

Alcune altre osservazioni:

Vedo il messaggio "inizio ciclo principale", quindi so che è ottenere il controllo. Poi, vedo "sleep% i", e dopo, niente.

Se I^C, quindi vedo "dormire fatto". Dopo circa 20 secondi, ottengo un'eccezione da self.run() che l'applicazione remota non ha risposto:

DBusException: org.freedesktop.DBus.Error.NoReply: Non ha ricevuto una risposta. Le possibili cause includono: l'applicazione remota non ha inviato una risposta, il criterio di sicurezza del bus messaggi ha bloccato la risposta, il timeout di risposta scaduto o la connessione di rete è stata interrotta.

Qual è il modo migliore per eseguire il mio codice keep alive all'interno del server?

Grazie,

risposta

6

è necessario attivare in modo esplicito quando si utilizza il multithreading gobject chiamando gobject.threads_init(). Vedi lo PyGTK FAQ per informazioni di base.

Accanto a questo, per lo scopo che stai descrivendo, i timeout sembrano essere più adatti. Utilizzare come segue:

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

Questa chiama la funzione keepalive ogni time_in_ms (milli) secondi. Ulteriori dettagli, di nuovo, possono essere trovati al PyGTK reference.

+0

Jro, Grazie per il suggerimento. Sono nuovo di questo e davvero non ho capito la relazione tra dbus/glib/gtk/gobject. tomeout_add() è esattamente quello che voglio. – fandingo