--- dbus-1.8.20/dbus/dbus-connection.c 2015-05-14 13:23:25.000000000 +0100 +++ dbus-1.8.20-patch/dbus/dbus-connection.c 2017-09-25 12:14:22.112258845 +0100 @@ -20,7 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ - +#include +#include #include #include "dbus-shared.h" #include "dbus-connection.h" @@ -312,6 +313,9 @@ dbus_bool_t dispatch_acquired; /**< Someone has dispatch path (can drain incoming queue) */ dbus_bool_t io_path_acquired; /**< Someone has transport io path (can use the transport to read/write messages) */ + /* A count of the number of sequential retries caused by the dispatch processing flag being set */ + unsigned char processing_retries; + unsigned int shareable : 1; /**< #TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more than once */ unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */ @@ -325,6 +329,7 @@ unsigned int disconnected_message_processed : 1; /**< We did our default handling of the disconnected message, * such as closing the connection. */ + unsigned int processing : 1; /**< TRUE if dispatch processing is in progress */ #ifndef DBUS_DISABLE_CHECKS unsigned int have_connection_lock : 1; /**< Used to check locking */ @@ -1215,17 +1220,40 @@ if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending)) { _dbus_verbose ("pending call completed while acquiring I/O path"); + connection->processing_retries = 0; } else if ( (pending != NULL) && _dbus_connection_peek_for_reply_unlocked (connection, _dbus_pending_call_get_reply_serial_unlocked (pending))) { _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)"); + connection->processing_retries = 0; + } + else if ( connection->processing ) + { + _dbus_verbose ("connection processing while acquiring I/O path, retries %d", connection->processing_retries); + struct timespec tick = { 0, 1000000 }; + + switch(connection->processing_retries) + { + case 0: + connection->processing_retries = 1; + break; + + case 1: + connection->processing_retries = 2; + sched_yield(); + break; + + default: + nanosleep(&tick, NULL); + } } else { _dbus_transport_do_iteration (connection->transport, flags, timeout_milliseconds); + connection->processing_retries = 0; } _dbus_connection_release_io_path (connection); @@ -2525,7 +2553,7 @@ { /* block again, we don't have the reply buffered yet. */ _dbus_connection_do_iteration_unlocked (connection, - NULL, + pending, DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK, timeout_milliseconds - elapsed_milliseconds); @@ -4622,11 +4650,13 @@ reply_serial); if (pending) { + connection->processing = 1; _dbus_verbose ("Dispatching a pending reply\n"); complete_pending_call_and_unlock (connection, pending, message); pending = NULL; /* it's probably unref'd */ CONNECTION_LOCK (connection); + connection->processing = 0; _dbus_verbose ("pending call completed in dispatch\n"); result = DBUS_HANDLER_RESULT_HANDLED; goto out;