--- dbus/dbus-transport-unix.c +++ dbus/dbus-transport-unix.c @@ -594,9 +594,10 @@ if (bytes_written < 0) { /* EINTR already handled for us */ - if (errno == EAGAIN || - errno == EWOULDBLOCK) + errno == EWOULDBLOCK || + /* we don't want to throw away lingering read-able data on write failure */ + errno == EPIPE) goto out; else { --- dbus/dbus-watch.c +++ dbus/dbus-watch.c @@ -51,6 +51,12 @@ unsigned int enabled : 1; /**< Whether it's enabled. */ }; +dbus_bool_t +_dbus_watch_get_enabled (DBusWatch *watch) +{ + return watch->enabled; +} + /** * Creates a new DBusWatch. Used to add a file descriptor to be polled * by a main loop. --- dbus/dbus-watch.h +++ dbus/dbus-watch.h @@ -68,6 +68,7 @@ void _dbus_watch_list_toggle_watch (DBusWatchList *watch_list, DBusWatch *watch, dbus_bool_t enabled); +dbus_bool_t _dbus_watch_get_enabled (DBusWatch *watch); DBUS_END_DECLS --- dbus/dbus-transport-unix.c +++ dbus/dbus-transport-unix.c @@ -783,6 +783,28 @@ } static dbus_bool_t +unix_error_with_read_to_come (DBusTransport *itransport, + DBusWatch *watch, + unsigned int flags) +{ + DBusTransportUnix *transport = (DBusTransportUnix*) itransport; + if (flags & DBUS_WATCH_ERROR) + return TRUE; + + if ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE)) + { + /* If we have a read watch enabled ... + we -might have data incoming ... => handle the HANGUP there */ + if (watch != transport->read_watch && + _dbus_watch_get_enabled (transport->read_watch)) + return FALSE; + + return TRUE; + } + return FALSE; +} + +static dbus_bool_t unix_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int flags) @@ -799,8 +820,7 @@ * of its max_bytes_read_per_iteration limit). The condition where * flags == HANGUP (without READABLE) probably never happen in fact. */ - if ((flags & DBUS_WATCH_ERROR) || - ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE))) + if (unix_error_with_read_to_come (transport, watch, flags)) { _dbus_verbose ("Hang up or error on watch\n"); _dbus_transport_disconnect (transport);