diff options
Diffstat (limited to 'dbus/dbus-connection.c')
-rw-r--r-- | dbus/dbus-connection.c | 123 |
1 files changed, 82 insertions, 41 deletions
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index e46fbc3d..a59b1a0c 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ @@ -889,21 +889,34 @@ _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, timeout = _dbus_pending_call_get_timeout_unlocked (pending); - if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) - return FALSE; - - if (!_dbus_hash_table_insert_int (connection->pending_replies, - reply_serial, - pending)) + if (timeout) { - _dbus_connection_remove_timeout_unlocked (connection, timeout); + if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) + return FALSE; + + if (!_dbus_hash_table_insert_int (connection->pending_replies, + reply_serial, + pending)) + { + _dbus_connection_remove_timeout_unlocked (connection, timeout); - _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); - HAVE_LOCK_CHECK (connection); - return FALSE; + _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); + HAVE_LOCK_CHECK (connection); + return FALSE; + } + + _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); + } + else + { + if (!_dbus_hash_table_insert_int (connection->pending_replies, + reply_serial, + pending)) + { + HAVE_LOCK_CHECK (connection); + return FALSE; + } } - - _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); _dbus_pending_call_ref_unlocked (pending); @@ -2194,8 +2207,10 @@ connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *conn _dbus_pending_call_queue_timeout_error_unlocked (pending, connection); - _dbus_connection_remove_timeout_unlocked (connection, - _dbus_pending_call_get_timeout_unlocked (pending)); + + if (_dbus_pending_call_is_timeout_added_unlocked (pending)) + _dbus_connection_remove_timeout_unlocked (connection, + _dbus_pending_call_get_timeout_unlocked (pending)); _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); _dbus_hash_iter_remove_entry (&iter); @@ -2266,12 +2281,12 @@ void _dbus_connection_block_pending_call (DBusPendingCall *pending) { long start_tv_sec, start_tv_usec; - long end_tv_sec, end_tv_usec; long tv_sec, tv_usec; DBusDispatchStatus status; DBusConnection *connection; dbus_uint32_t client_serial; - int timeout_milliseconds; + DBusTimeout *timeout; + int timeout_milliseconds, elapsed_milliseconds; _dbus_assert (pending != NULL); @@ -2291,19 +2306,23 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending) * in _dbus_pending_call_new() so overflows aren't possible * below */ - timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending)); - - _dbus_get_current_time (&start_tv_sec, &start_tv_usec); - end_tv_sec = start_tv_sec + timeout_milliseconds / 1000; - end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000; - end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND; - end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND; + timeout = _dbus_pending_call_get_timeout_unlocked (pending); + if (timeout) + { + timeout_milliseconds = dbus_timeout_get_interval (timeout); + _dbus_get_current_time (&start_tv_sec, &start_tv_usec); + + _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", + timeout_milliseconds, + client_serial, + start_tv_sec, start_tv_usec); + } + else + { + timeout_milliseconds = -1; - _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n", - timeout_milliseconds, - client_serial, - start_tv_sec, start_tv_usec, - end_tv_sec, end_tv_usec); + _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); + } /* check to see if we already got the data off the socket */ /* from another blocked pending call */ @@ -2345,6 +2364,8 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending) } _dbus_get_current_time (&tv_sec, &tv_usec); + elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + + (tv_usec - start_tv_usec) / 1000; if (!_dbus_connection_get_is_connected_unlocked (connection)) { @@ -2359,15 +2380,36 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending) dbus_pending_call_unref (pending); return; } - else if (tv_sec < start_tv_sec) - _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); else if (connection->disconnect_message_link == NULL) _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); - else if (tv_sec < end_tv_sec || - (tv_sec == end_tv_sec && tv_usec < end_tv_usec)) + else if (timeout == NULL) + { + if (status == DBUS_DISPATCH_NEED_MEMORY) + { + /* Try sleeping a bit, as we aren't sure we need to block for reading, + * we may already have a reply in the buffer and just can't process + * it. + */ + _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); + + _dbus_memory_pause_based_on_timeout (timeout_milliseconds); + } + else + { + /* block again, we don't have the reply buffered yet. */ + _dbus_connection_do_iteration_unlocked (connection, + DBUS_ITERATION_DO_READING | + DBUS_ITERATION_BLOCK, + timeout_milliseconds); + } + + goto recheck_status; + } + else if (tv_sec < start_tv_sec) + _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); + else if (elapsed_milliseconds < timeout_milliseconds) { - timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 + - (end_tv_usec - tv_usec) / 1000; + timeout_milliseconds -= elapsed_milliseconds; _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds); _dbus_assert (timeout_milliseconds >= 0); @@ -3231,10 +3273,8 @@ reply_handler_timeout (void *data) * * If -1 is passed for the timeout, a sane default timeout is used. -1 * is typically the best value for the timeout for this reason, unless - * you want a very short or very long timeout. There is no way to - * avoid a timeout entirely, other than passing INT_MAX for the - * timeout to mean "very long timeout." libdbus clamps an INT_MAX - * timeout down to a few hours timeout though. + * you want a very short or very long timeout. If INT_MAX is passed for + * the timeout, no timeout will be set and the call will block forever. * * @warning if the connection is disconnected or you try to send Unix * file descriptors on a connection that does not support them, the @@ -3246,7 +3286,7 @@ reply_handler_timeout (void *data) * object, or #NULL if connection is disconnected or when you try to * send Unix file descriptors on a connection that does not support * them. - * @param timeout_milliseconds timeout in milliseconds or -1 for default + * @param timeout_milliseconds timeout in milliseconds, -1 for default or INT_MAX for no timeout * @returns #FALSE if no memory, #TRUE otherwise. * */ @@ -3379,7 +3419,7 @@ dbus_connection_send_with_reply (DBusConnection *connection, * * @param connection the connection * @param message the message to send - * @param timeout_milliseconds timeout in milliseconds or -1 for default + * @param timeout_milliseconds timeout in milliseconds, -1 for default or INT_MAX for no timeout. * @param error return location for error message * @returns the message that is the reply or #NULL with an error code if the * function fails. @@ -5440,6 +5480,7 @@ dbus_connection_remove_filter (DBusConnection *connection, } link = _dbus_list_get_prev_link (&connection->filter_list, link); + filter = NULL; } CONNECTION_UNLOCK (connection); |