summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-connection.c')
-rw-r--r--dbus/dbus-connection.c123
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);