Running mainloop within a thread

Tom Vaughan tom at software6.net
Tue Dec 30 09:06:22 PST 2008


Hi,

Please forgive me if this has been covered already. My attempts to
search the archives turned up empty.

I want to have a unittest module that starts a dbus test service, runs
some tests, and then stops the dbus test service. This means, I
assume, I have to run the mainloop within a thread. For example:

class TestDaemon(dbus.service.Object, threading.Thread):

        def run(self):
                self.__loop = gobject.MainLoop()
                self.__loop.run()

        [snip]

        def __init__(self):
                gobject.threads_init()

                dbus.mainloop.glib.threads_init()
                dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

                # these are assigned so they do not go out-of-scope
and get garbage collected
                self.__sessionbus = dbus.SessionBus()
                self.__busname =
dbus.service.BusName(resconn.namespace, self.__sessionbus)

                dbus.service.Object.__init__(self, self.__sessionbus, '/Test')

                threading.Thread.__init__(self)
                self.setDaemon(True)

class TestCase(unittest.TestCase):

        def setUp(self):
                daemon = TestDaemon()
                daemon.start()

        [snip]

This works, sort of. Everything is fine until I run a test that
transfers a large amount of data over dbus. I run the same test 10
times. The first 1 or 2 iterations are OK, and then the dbus test
services appears to die. If I don't start the dbus test service within
the unittest module, but rather in a separate script, everything is
hunky dory.

Any clues what I any doing wrong? Thanks. Full source code is below.

-Tom

import sys
import threading
import time
import unittest

import numpy

import gobject

import dbus
import dbus.service
import dbus.mainloop.glib

import resconn
import wrapper.restest as wrapper

class TestDaemon(dbus.service.Object, threading.Thread):

        def run(self):
                self.__loop = gobject.MainLoop()
                self.__loop.run()

        @resconn.benchmark
        def tolist(self, length, rawdata):
                return [rawdata[i] for i in range(0, length)]

        @resconn.benchmark
        @dbus.service.method(resconn.namespace, in_signature='d',
out_signature='d')
        def DBUSTest0(self, value):
                return value

        @resconn.benchmark
        @dbus.service.method(resconn.namespace, in_signature='d',
out_signature='d')
        def DBUSTest1(self, value):
                test1 = wrapper.cds_restest_dbus_test1(value)
                return test1

        @resconn.benchmark
        @dbus.service.method(resconn.namespace, in_signature='d',
out_signature='(uad)')
        def DBUSTest2(self, value):
                test2 = wrapper.cds_restest_dbus_test2(value)
                ndoubles = test2.ndoubles
                doubles = self.tolist(ndoubles,
wrapper.doubles.frompointer(test2.doubles))
                return [ndoubles, doubles]

        @resconn.benchmark
        @dbus.service.method(resconn.namespace, in_signature='ud',
out_signature='(ad)')
        def DBUSTest3(self, length, value):
                test3 = wrapper.cds_restest_dbus_test3(length, value)
                return test3

        @resconn.benchmark
        @dbus.service.method(resconn.namespace, in_signature='',
out_signature='')
        def Exit(self):
                self.__loop.quit()

        def __init__(self):
                gobject.threads_init()

                dbus.mainloop.glib.threads_init()
                dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

                # these are assigned so they do not go out-of-scope
and get garbage collected
                self.__sessionbus = dbus.SessionBus()
                self.__busname =
dbus.service.BusName(resconn.namespace, self.__sessionbus)

                dbus.service.Object.__init__(self, self.__sessionbus, '/Test')

                threading.Thread.__init__(self)
                self.setDaemon(True)

class TestClient(resconn.Object):

        def __new__(self):
                self.__object =
dbus.SessionBus().get_object(resconn.namespace, '/Test')
                return dbus.Interface(self.__object, resconn.namespace)

class TestCase(unittest.TestCase):

        def setUp(self):
                daemon = TestDaemon()
                daemon.run()

                try:
                        self.client = TestClient()
                except Exception, detail:
                        print detail

        def tearDown(self):
                self.client.Exit()

        @resconn.benchmark
        def testDBUS(self):

                @resconn.benchmark
                def testDBUS0():
                        value = 12.34
                        t1 = time.time()
                        rc1 = self.client.DBUSTest0(value)
                        t2 = time.time()
                        print 'D-BUS Test 0...',
                        if value != rc1:
                                print 'FAILED! value = %.04f rc =
%.04f' % (value, rc1)
                                passed = False
                        else:
                                print 'PASSED!'
                                passed = True

                        return passed, t2 - t1

                @resconn.benchmark
                def testDBUS1():
                        value = 12.34
                        t1 = time.time()
                        rc1 = self.client.DBUSTest1(value)
                        t2 = time.time()
                        print 'D-BUS Test 1...',
                        if value != rc1:
                                print 'FAILED! value = %.04f rc =
%.04f' % (value, rc1)
                                passed = False
                        else:
                                print 'PASSED!'
                                passed = True

                        return passed, t2 - t1

                @resconn.benchmark
                def testDBUS2():
                        value = 12.34
                        t1 = time.time()
                        rc1 = self.client.DBUSTest2(value)
                        t2 = time.time()
                        print 'D-BUS Test 2...',
                        print 'PASSED!'
                        passed = True

                        return passed, t2 - t1

                def test(f):
                        times = []
                        niters = 10
                        for i in range(0, niters):
                                passed, elapsed = f()
                                times.append(elapsed)

                        print '%s: niters = %d' % (f.__name__, niters)
                        print 'min = %.04f s max = %.04f s mean =
%.04f s std = %.04f s' % \
                          (min(times), max(times), numpy.mean(times),
numpy.std(times))

                test(testDBUS0)
                test(testDBUS1)
                test(testDBUS2)

def testsuite():
        __testsuite = unittest.TestSuite()
        __testsuite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestCase))
        return __testsuite

# $Id:$
#
# Local Variables:
# indent-tabs-mode: nil
# python-continuation-offset: 2
# python-indent: 8
# End:
# vim: ai et si sw=8 ts=8


-- 
Website: www.software6.net
E-mail/Google Talk: tom (at) software6 (dot) net
Mobile: +1 (310) 704-0787


More information about the dbus mailing list