ignoring a process' last words: SIGPIPE ...

Avery Pennarun apenwarr at gmail.com
Thu Mar 27 10:53:52 PDT 2008


On Thu, Mar 27, 2008 at 10:01 AM, Havoc Pennington <hp at pobox.com> wrote:
>  Anyway, I think the daemon requires some hacking to basically keep
>  credentials and remaining incoming messages around even though the
>  connection is closed. I don't know if this will be easy or involve
>  some challenges. I would start by adding a case to the daemon test
>  suite (which is mostly stuffed in bus/dispatch.c) illustrating the
>  problem.

The problem here is that both ends of the connection (dbus-send and
dbus-daemon) are violating Jon Postel's rule for successful
communication: "be conservative in what you do, be liberal in what you
accept from others."  If either one was fixed, this problem would go
away.

In general, most Internet protocols are designed around this rule by
having the client *request* disconnection, and then having the server
disconnect only after receiving this request.  That way, neither end
is surprised.

In this case, dbus-send is disconnecting without telling the server,
and the server doesn't deal well with the surprise.

One perfectly good solution, as proposed already, is to use the
--print-reply option to dbus-send, which forces it to stay connected
until it gets the answer back.  In fact, this isn't such a bad idea
either way.

Another solution is to make dbus-daemon more robust:

Remember that sockets are bi-directional and can close each direction
independently.  What EPIPE means is that your send direction has been
closed whether you like it or not; that says nothing at all about your
receive direction.  Often, a safe approach is to only consider your
socket "closed" when you get an error on receive, and ignore it when
you get an error (except EAGAIN, of course) on send.  But beware, if
you do that, you can get into the opposite situation of losing a reply
to go back to the client even though you got an EOF when reading from
the client.  (A client can make this happen to you by using the
shutdown() system call on its end to close down only its transmit
path.  HTTP clients do this a lot.)

In the case of dbus-daemon, I'd think it should be safe to just ignore
EPIPE and pretend the data has been written.  Remember, the socket
isn't really "closed" until you close it, and the fd will remain valid
and won't be reused, so there's no reason to throw away any
authentication data structures, etc. The socket will close just fine
next time through the normal execution path where select() returns
true for readable, and then read() returns 0 bytes (EOF).

Note that a really super-excellent fix might wait until a socket gives
EOF on read *and* the output buffer is empty.  But since it's doubtful
that any dbus clients actually use shutdown(), this is less important.

Have fun,

Avery
 who has obviously suffered too much in his life


More information about the dbus mailing list