about signals

Olivier Andrieu oliv__a at users.sourceforge.net
Thu May 27 16:09:06 PDT 2004


 Havoc Pennington <hp at redhat.com> [Thu, 27 May 2004 16:01:32 -0400]:
 > 
 > On Thu, 2004-05-27 at 09:50, Olivier Andrieu wrote:
 > > Hi,
 > > 
 > > I found this interesting thread in the list archives: 
 > > http://freedesktop.org/pipermail/dbus/2003-September/000488.html
 > > http://freedesktop.org/pipermail/dbus/2003-October/000499.html
 > > 
 > > This is about the fact that one cannot send a signal *as* a particular
 > > service, in other words signal messages always have a base service in
 > > the SENDER header field. Seth suggested that the signal emitter set
 > > the SENDER to a particular service.
 > > 
 > > I think that's quite reasonable in fact and that would more consistent
 > > than the actual (unimplemented) solution.
 > 
 > The issues I raised in those archived mails still seem relevant
 > though... ?

Well I don't known, you agreed « that's a bit odd » and then you said
having the client setting the sender « makes their API all fugly »,
which didn't quite convince me :)

 > I think the conceptual complexity is that a well-known service name is
 > used to locate a _connection_ or _application_, a unique base service
 > name is used to _identify_ said connection/application, and a
 > connection/application plus an object path is used to identify an object
 > instance. Then of course signals are emitted by object instances, not by
 > connections/applications.
 >
 > The root problem here is probably having both concepts "object" and
 > "connection/application" - and both "services" and "interfaces."

The way I see it, services are not conceptually different from object
paths and interfaces, it's part of the naming of a remote piece of
code: service designates an application (process), the path designates
an object (whatever that means in the language the remote application
was written in), the interface + member name designates a method in
the object.  So, the fact the service corresponds to a connection, a
socket is only an implementation detail.

 > Imagine that we didn't have the bus, and instead we had a bunch of
 > domain sockets:
 >   /var/dbus-using-daemons/org.freedesktop.HALDaemon
 >   /var/dbus-using-daemons/blah.Blah
 > 
 > This would be more or less equivalent to the idea of a service. If you
 > connected to the socket blah.Blah you'd expect it to be a particular
 > daemon, but you wouldn't expect to use the name blah.Blah on an ongoing
 > basis as you talk to it.

Well I would. Why not ? When I'm browsing pages at freedesktop.org,
I'm using this name on an ongoing basis (viewing
freedesktop.org/Software/Home, freedesktop.org/Software/dbus, etc.)
even though that's just a way to 'locate' 131.252.208.82 .

Anyway, the problem is about 'connecting' signals. The way the glib
API works right now is to present proxies to a service + object +
interface triplet.  That's fine for sending method calls and here the
unique name is necessary to correctly route the reply back, as you've
shown in your message.  But to make sure an incoming signal should be
handled by a proxy, right now we require _all_ the clients to do some
tracking which is in fact unnecessary because the bus has already
the check. Right now this happens:

 - proxy from app A wants signals from blah.Blah:/object/foo, it adds
a match rule with sender=blah.Blah
 - when a signal arrives from :1-42, the bus checks if :1-42 is the
primary owner of blah.Blah
 - if yes it sends the message to app A
 - app A sees a signal coming from :1-42 and /a priori/ it doesn't
know if it should be handled by proxy blah.Blah or foo.Bar, so it has
to track service ownership and check wether blah.Blah is indeed owned
by :1-42

So, we could avoid this redundant check which happens in _all_
listeners and replace it by requiring the emitter to fill in the
service (and the bus would continue its check to see if the emitter is
not lying about its service ownership).

As for the API, that's a minimal change. We have:
DBusMessage* dbus_message_new_method_call   (const char  *service,
                                             const char  *path,
                                             const char  *interface,
                                             const char  *method);
and we would have:
DBusMessage* dbus_message_new_signal        (const char  *service,
                                             const char  *path,
                                             const char  *interface,
                                             const char  *name);

Both have the triplet service+path+interface, locating destination for
the method_call and locating origin for the signal. It's just
symmetric. 

I would even go further and say that unique service names and
well-known service names are in fact different types. They should not
be mixed and a high-level binding such as the glib one can completely
hide unique names.  A method call never needs to use a unique name as
its destination service: the way an application learns about unique
names is through service announcements messages or activation
messages. So it's always linked with a real service name. Conversely,
an application would be required to own a service before sending a
signal. Simple rule: you need a real service name to send, either a
message or a signal.

Anyway, we're almost in agreement when you say: « my view is that the
daemon should either require or forbid a sender set by the sender
app. » I just think it should be
 - require a sender set by the sender app for signals
 - forbid  a sender set by the sender app for methods

 > Remember signal emission/listening is supposed to work without a bus
 > daemon at all, in the context of just a direct 1-to-1 connection.
 > In that scenario the equivalent of keying your listener code off the
 > service would be changing behavior depending on whether you connected to
 > "host", "host.bar.com", or "localhost" to establish the connection.

I'm not sure I understand this. Services are about the bus routing
and/or dropping messages, i.e. all service-dependent handling is done
in the bus dameon. In the 1-to-1 case messages alway go directly to
the peer. 

-- 
   Olivier



More information about the dbus mailing list