Unix FD Passing

Lennart Poettering mzqohf at 0pointer.de
Wed May 20 13:01:45 PDT 2009


On Fri, 15.05.09 22:08, Havoc Pennington (hp at pobox.com) wrote:

Heya,

> Not sure I'm reading the code properly but it looks to me like we
> don't synthesize timeout errors unless you use send_with_reply();
> send_preallocated() and send() don't do the client-side synthetic
> replies, so you are not guaranteed to ever get a reply at all, while
> send_with_reply() guarantees you get a timeout if nothing else. So we
> could perhaps copy how timeouts work - only have an error reply if you
> use send_with_reply() (or _and_block()). Using plain send(), it would
> be as if the remote app didn't reply or was locked up.
> 
> That's essentially what you've done here already (only _and_block()
> sets a DBusError, right, the others just kind of silently don't send
> anything).
> 
> Implementation-wise, what this would look like is that we'd silently
> fail for the no-reply flavors as you are doing already; and for the
> _with_reply flavors (with a DBusPendingCall internally), where we
> preallocate a timeout now in the PendingCall, we'd preallocate a "no
> fd support" error instead. Change the timeout_link in PendingCall to
> error_link or something.
> 
> Not sure, but seems like it would usually do as close to the right
> thing as possible - error reply or else /dev/null.

I have now looked closer at this (and actually wrote code which I
subsequently reverted). And I now think that synthesizing an
asynchronous error response for dbus_connection_send_with_reply()
would be a bad choice.

There are four calls for sending a message:

1) dbus_connection_send() -- there is no path to return errors at all
(except OOM). The best we can do is fail silently and expect the user
to check with _can_send_type() first.

2) dbus_connection_send_preallocated() -- this is the same case as
dbus_connection_send().

3) dbus_connection_send_with_reply_and_block() -- this allows us to
return a proper, synchronous error, which the current already patch
does.

4) dbus_connection_send_with_reply() -- this is the special case. It
doesn't have a way to signal proper error codes synchronously (except
OOM), but at least it has a way to distuingish OOM from other errors
(OOM returns FALSE, non-OOM returns TRUE and sets *pending_return to
NULL).

Only case 4) is what this discussion is about, right? There are the
two options to a) make it work like dbus_connection_send() and just
fail synchronously or b) make it succeed, return a proper
DBusPendingCall but then immediately synthesize an error message on
that async function call object, i.e. make it fail asynchronously.

Sending an unix fd on a connection that cannot handle it is not a
typical runtime error, it is a (local) programming error. Also the
error is by its very nature synchronous. One can certainly turn it
into an asynchronous error, but generally I think synchronous errors
are much easier to handle than asynchronous errors. Timeout errors
OTOH which you mentioned are asynchronous by their nature, so
returning asynchronous error message is not just an option but the
only thing that makes sense.

The only reason I see to trigger an asynchrnous error here is because
there is no other way to actually encode an error cause. However,
because this is a programming error and not so likely a runtime error
I don't think that distinguishing error causes explicitly would be
useful, especially since it would be much harder to handle
asynchronous errors than synchronous errors. 

And finally I see some benefit if the four functions would handle the
same things in similar ways.

So, for me it doesn't 'feel right' if we'd synthesize an async error
message here. 

Havoc, what do you say?

Lennart

-- 
Lennart Poettering                        Red Hat, Inc.
lennart [at] poettering [dot] net
http://0pointer.net/lennart/           GnuPG 0x1A015CC4


More information about the dbus mailing list