Search code examples
clinuxdbus

Does D-Bus guarantee message delivery?


I would like to know if D-Bus guarantees message delivery when used directly through the low level C API call dbus_connection_send_with_reply?

More specifically, does it guarantee that a single instance of a messages is delivered to the destination or if it fails that an error reply is returned?

I understand that the receiving application may not issue a reply to a method in which case D-Bus will return an error after a timeout. However, are all other potential failures covered by the D-Bus protocol?


Solution

  • tl;dr:

    Delivery can never be guaranteed. However, even if the message is not delivered, you can expect an error reply to say so.

    If you use DBUS_TIMEOUT_INFINITE, you might wait forever for a reply. If the function call returns FALSE, there will be no reply. Otherwise, you will get exactly one.


    I am an upstream maintainer of D-Bus, the message passing protocol specification, and dbus, the reference implementation of D-Bus.

    Terminology: your process calling dbus_connection_send_with_reply() is the client, the process that is expected to reply is the service. Normally there would be a dbus-daemon in between, although connecting directly to a service is possible in specialized situations (if you are doing this, then you should already know you are doing so).

    In general, the API guarantee is that if dbus_connection_send_with_reply() succeeds (returns TRUE), you will see exactly one reply, which can either be a successful return (only if the message was delivered) or an error (which can happen whether the message was delivered or not). If it fails due to out-of-memory or other pathological conditions (returns FALSE), you will see exactly no replies. The implementation goes to considerable lengths to ensure this.

    Before dbus_connection_send_with_reply() returns, it preallocates the synthetic error message that you will receive if the call times out; if that fails, the message is not sent and dbus_connection_send_with_reply() fails. So even if the dbus-daemon or the transport drops the real (success or error) reply on the floor, you will get the timeout error message eventually. (Reference: git grep _dbus_pending_call_set_timeout_error_unlocked in a copy of the dbus source code)

    The one exception to that API guarantee is if you use DBUS_TIMEOUT_INFINITE for the timeout (in which case: you asked for it, you got it). In that case, there are situations where you will never see a reply: either the service never responds but remains on the bus; or, more pathologically, the service never responds and leaves the bus, and the dbus-daemon runs out of memory while attempting to deliver the error reply that it synthesizes as a way to report that there will never be a reply from the service.