chiark / gitweb /
bus-proxy: make StartServiceByName synchronous
authorDavid Herrmann <dh.herrmann@gmail.com>
Fri, 31 Jul 2015 11:25:04 +0000 (13:25 +0200)
committerSven Eden <yamakuzure@gmx.net>
Tue, 14 Mar 2017 09:07:22 +0000 (10:07 +0100)
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.

With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).

Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.

This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.

Note:
        This race was triggered by gdbus. The gdbus-proxy implementation
        relies on a name to be available after StartServiceByName()
        returns. This is highly fragile and should be dropped by gdbus.
        Even if the call is synchronous, there is no reason whatsoever to
        assume the service did not exit-on-idle before ListNames()
        returns.
        However, this race is much less likely than the startup race, so
        we try to be compatible to dbus-daemon now.

src/libelogind/sd-bus/bus-introspect.h

index ccb951c1092cc00e8b1d323721bcbd9e73c8a9fe..6aac650ac93a8e469e3cadfc97f51d34b756a99b 100644 (file)
@@ -25,6 +25,9 @@
 #include "bus-xml-policy.h"
 
 typedef struct Proxy Proxy;
 #include "bus-xml-policy.h"
 
 typedef struct Proxy Proxy;
+typedef struct ProxyActivation ProxyActivation;
+
+#define PROXY_ACTIVATIONS_MAX (16) /* max parallel activation requests */
 
 struct Proxy {
         sd_bus *local_bus;
 
 struct Proxy {
         sd_bus *local_bus;
@@ -37,12 +40,22 @@ struct Proxy {
         Set *owned_names;
         SharedPolicy *policy;
 
         Set *owned_names;
         SharedPolicy *policy;
 
+        LIST_HEAD(ProxyActivation, activations);
+        size_t n_activations;
+
         bool got_hello : 1;
         bool queue_overflow : 1;
         bool message_matched : 1;
         bool synthetic_matched : 1;
 };
 
         bool got_hello : 1;
         bool queue_overflow : 1;
         bool message_matched : 1;
         bool synthetic_matched : 1;
 };
 
+struct ProxyActivation {
+        LIST_FIELDS(ProxyActivation, activations_by_proxy);
+        Proxy *proxy;
+        sd_bus_message *request;
+        sd_bus_slot *slot;
+};
+
 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest);
 Proxy *proxy_free(Proxy *p);
 
 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest);
 Proxy *proxy_free(Proxy *p);