2011-10-12 17 views
6

Zaczynam od programowania w trybie DBus i programowania sterowanego zdarzeniami. Usługa, którą próbuję utworzyć, składa się naprawdę z trzech części, ale dwie są naprawdę "serwerowymi" rzeczami.Główna pętla magistrali Dbus/GLib, wątek tła

1) Aktualny serwer DBus rozmawia ze zdalną witryną za pośrednictwem protokołu HTTPS, zarządza sesjami i przekazuje informacje klientom.

2) Druga część serwisu nazywa podtrzymanie strony co 2 minuty, aby utrzymać sesję aktywny na stronie zewnętrznej

3) klientom wykonywanie połączeń do serwisu, aby pobrać informacje z serwisu.

Znalazłem kilka prostych przykładowych programów. Próbuję dostosować je do prototypów nr 1 i nr 2. Zamiast budować osobne programy dla obu. Myślałem, że mogę je uruchomić w jednym, dwu wątkowym procesie.

Problem, który widzę, polega na tym, że nazywam time.sleep (X) w wątku keep keep alive. Nić idzie spać, ale nigdy się nie obudzi. Myślę, że GIL nie został wydany przez główną pętlę GLib.

Oto mój kod wątek:

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

Z wypowiedzi drukowania, wiem, że rozpoczyna się spać, ale nigdy nie zobaczyć „uśpienia zrobić.”

Oto kod główny:

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

Niektóre inne obserwacje:

widzę komunikat „rozpocząć główną pętlę”, więc wiem, że robi się kontroli. Następnie widzę "sleep% i", a potem nic.

Jeśli I^C, to widzę "snu zrobione". Po ~ 20 sekund, pojawia się wyjątek od self.run(), że zdalna aplikacja nie odpowiada:

DBusException: org.freedesktop.DBus.Error.NoReply: nie otrzymał odpowiedzi. Możliwe przyczyny: aplikacja zdalna nie wysłała odpowiedzi, zasady bezpieczeństwa magistrali komunikatów zablokowały odpowiedź, upłynął limit czasu odpowiedzi lub połączenie sieciowe zostało zerwane.

Jaki jest najlepszy sposób na uruchomienie mojego kodu utrzymywanego na serwerze?

Dzięki,

Odpowiedz

6

Trzeba przy użyciu gobject wywołując gobject.threads_init() jawnie włączyć wielowątkowość. Aby uzyskać dodatkowe informacje, patrz PyGTK FAQ.

Oprócz tego, dla celów, które opisujesz, limity czasu wydają się być lepszym rozwiązaniem. Używać w następujący sposób:

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

To wywołuje funkcję keepalive co time_in_ms (mili) sekund. Więcej szczegółów można znaleźć na stronie PyGTK reference.

+0

Jro, dzięki za sugestię. Jestem na tym początku i naprawdę nie rozumiem związku między dbus/glib/gtk/gobject. tomeout_add() jest dokładnie tym, czego chcę. – fandingo