Re: DBus Specification questions

Simon McVittie <smcv-ZGY8ohtN/[email protected]>
Newsgroups gmane.comp.freedesktop.dbus
Message-ID <20200331204250.GA1831779@horizon>
On Tue, 31 Mar 2020 at 14:22:22 -0400, Robert Middleton wrote:
> Related question: I know that there have been issues with libdbus and
> multithreading, any thoughts on how to best handle this?

libdbus tries to be all things to all people, and support any or no
event-loop abstraction. Whatever you do, don't do that.

If your runtime environment has an event-loop abstraction with a coherent
model for how things are meant to work, like GLib's GMainContext or
Qt's...  QApplication? (it's a while since I've used Qt), then please
use that, and require your API users to use it too.

If you are inventing your own thing, decide whether each object is:

- fully thread-safe (any thread can call any externally-exposed method,
  signals/callbacks should document which context/thread they will get
  called in - this is hard to get right, and you will probably end up
  needing a worker thread that does all the actual I/O. See: GDBus)

- single-threaded (each thread must have its own separate instance of
  this object, and no other thread is allowed to touch it;
  see: systemd's sd-bus)

- something else (dangerous)

Definitely don't do what libdbus does, where the actual I/O might happen
in any thread or any mixture of threads according to the whim of the host
application, and there's an elaborate dance involving two overlapping
mutexes for a thread to get ownership of the I/O path, the ability to
dispatch messages to callbacks, or maybe both...

> I wasn't completely sure as there is an error
> org.freedesktop.DBus.Error.NoReply, which at least implies(to me) that
> this can come from other places.

Some implementations, like libdbus, use a D-Bus-style error name
and error message pair, synthesized locally rather than derived
from a message, to report errors. In particular, libdbus uses
org.freedesktop.DBus.Error.NoReply to signal "I was expecting a reply,
but then I timed out" to its callers. This avoids having to invent a
second, parallel error-reporting mechanism where D-Bus error messages
go through one API, locally-generated errors go through another, and
callers have to check two error indicators - libdbus usually turns all
error conditions into a DBusError object.

The vocabulary of standard D-Bus errors includes some that are only sent
and received over the bus, some that would only be synthesized locally
(notably Disconnected - how would you ever receive that?), and some that
can happen either way (like NoReply).

I don't think systemd's sd-bus does that so much: it uses a (name,
message) pair for error messages received from the bus, but returns a
negative errno code for locally-generated errors. That's also a valid
approach, with advantages and disadvantages. I personally prefer libdbus'
approach here, but it's a question of how you design your API.

In bindings/implementations for high-level languages (like dbus-python)
and bindings/implementations for low-level languages pretending to be
high-level via a runtime library (like GDBus), it's common to represent
both D-Bus error messages and locally-generated errors as an error object
or exception, whatever the language/runtime would normally use. For example,
dbus-python raises Python exceptions and GDBus raises GLib GErrors. In a
high-quality binding/implementation there'll usually be a way to extract
the D-Bus error name from the exception, so that you can match specific
errors by their machine-readable name if that makes sense in your
application.

> Now that I think about it though,
> can the daemon ever respond back with an error?

The dbus-daemon can respond to method calls with errors instead of
relaying them to a destination, yes. The system bus does this when it
needs to raise AccessDenied.

It can raise NoReply in two situations:

- the service that was meant to reply disconnected from the bus
  (e.g. crashed) before it had a chance to reply;

- the dbus-daemon has been configured to put a maximum timeout on
  all method calls (as I said, this has not been the default for a long
  time, but it is still possible to configure) and that timeout was reached

> Is there a list of
> well-known errors and who is responsible for generating the error?

The list of well-known errors is in dbus/dbus-protocol.h, but unfortunately
the circumstances in which each one is intended to be generated are not
really documented.

    smcv
_______________________________________________
dbus mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dbus
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.