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?
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.