summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@debian.org>2018-05-08 09:18:28 +0100
committerSimon McVittie <smcv@collabora.com>2018-05-09 08:53:34 +0100
commit62789b8dd79f2b29252f31c1f424cc43e4ca5ec5 (patch)
tree8714640bee744e561e9576cf0a9978b1498cf55b
parentd4732fae047c2d6532ad8049ae0edc2fb3480fe2 (diff)
cross-test-server: Avoid a race condition in the client
There is a race condition here between these chains of events, which as far as I can tell has existed for at least 10 years: * server receives Tests.Trigger() and schedules SignalTests.Triggered * server returns to main loop * server emits SignalTests.Triggered * client receives SignalTests.Triggered and * server receives Tests.Trigger() and replies with success * client receives success and emits SignalTests.Trigger * server receives SignalTests.Trigger and calls CallbackTests.Response() * client receives CallbackTests.Response() and calls Tests.Exit() * server receives Tests.Exit() and replies with success * client quits its main loop If we don't reply to Tests.Trigger() until after the SignalTests.Triggered signal has been sent, because the client called Tests.Trigger() asynchronously, messages are not re-ordered and the reply arrives after the signal; so the whole chain of events leading up to "client receives SignalTests.Triggered" happens before "client receives success and emits SignalTests.Trigger" and there is no race condition. Bug-Debian: https://bugs.debian.org/898158
-rwxr-xr-xtest/cross-test-server.py13
1 files changed, 9 insertions, 4 deletions
diff --git a/test/cross-test-server.py b/test/cross-test-server.py
index 313a063..30edb1c 100755
--- a/test/cross-test-server.py
+++ b/test/cross-test-server.py
@@ -274,15 +274,18 @@ class TestsImpl(dbus.service.Object):
@dbus.service.method(INTERFACE_TESTS, 'st', '',
connection_keyword='conn',
+ async_callbacks=('reply_cb', 'error_cb'),
**kwargs)
- def Trigger(self, object, parameter, conn=None):
+ def Trigger(self, object, parameter, conn=None, reply_cb=None,
+ error_cb=None):
assert isinstance(object, str)
logger.info('method/signal: client wants me to emit Triggered(%r) from %r', parameter, object)
tested_things.add(INTERFACE_TESTS + '.Trigger')
gobject.idle_add(lambda: self.emit_Triggered_from(conn, object,
- parameter))
-
- def emit_Triggered_from(self, conn, object, parameter):
+ parameter,
+ reply_cb))
+
+ def emit_Triggered_from(self, conn, object, parameter, reply_cb):
assert isinstance(object, str)
logger.info('method/signal: Emitting Triggered(%r) from %r', parameter, object)
obj = objects.get(object, None)
@@ -291,6 +294,8 @@ class TestsImpl(dbus.service.Object):
objects[object] = obj
obj.Triggered(parameter)
logger.info('method/signal: Emitted Triggered')
+ reply_cb()
+ logger.info('method/signal: Sent reply for Tests.Trigger()')
@dbus.service.method(INTERFACE_TESTS, '', '')
def Exit(self):