DBusDispatchStatus last_dispatch_status; /**< The last dispatch status we reported to the application. */
- DBusList *link_cache; /**< A cache of linked list links to prevent contention
- * for the global linked list mempool lock
- */
DBusObjectTree *objects; /**< Object path handlers registered with this connection */
char *server_guid; /**< GUID of server if we are in shared_connections, #NULL if server GUID is unknown or connection is private */
RELEASING_LOCK_CHECK (connection);
_dbus_mutex_unlock (connection->mutex);
- for (iter = _dbus_list_get_first_link (&expired_messages);
+ for (iter = _dbus_list_pop_first_link (&expired_messages);
iter != NULL;
- iter = _dbus_list_get_next_link (&expired_messages, iter))
+ iter = _dbus_list_pop_first_link (&expired_messages))
{
DBusMessage *message = iter->data;
dbus_message_unref (message);
- iter->data = NULL;
+ _dbus_list_free_link (iter);
}
-
- /* Take the lock back for a moment, to copy the links into the link
- * cache. FIXME: with this extra cost, is it still advantageous to have
- * the link cache? */
- _dbus_mutex_lock (connection->mutex);
-
- for (iter = _dbus_list_pop_first_link (&expired_messages);
- iter != NULL;
- iter = _dbus_list_pop_first_link (&expired_messages))
- _dbus_list_prepend_link (&connection->link_cache, iter);
-
- _dbus_mutex_unlock (connection->mutex);
}
/**
}
#ifdef DBUS_BUILD_TESTS
-/* For now this function isn't used */
-/**
- * Adds a message to the incoming message queue, returning #FALSE
- * if there's insufficient memory to queue the message.
- * Does not take over refcount of the message.
- *
- * @param connection the connection.
- * @param message the message to queue.
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_connection_queue_received_message (DBusConnection *connection,
- DBusMessage *message)
-{
- DBusList *link;
-
- link = _dbus_list_alloc_link (message);
- if (link == NULL)
- return FALSE;
-
- dbus_message_ref (message);
- _dbus_connection_queue_received_message_link (connection, link);
-
- return TRUE;
-}
-
/**
* Gets the locks so we can examine them
*
/* It's OK that in principle we call the notify function, because for the
* outgoing limit, there isn't one */
- _dbus_message_remove_counter (message, connection->outgoing_counter,
- &link);
-
- /* Save this link in the link cache also */
- _dbus_list_prepend_link (&connection->link_cache, link);
+ _dbus_message_remove_counter (message, connection->outgoing_counter);
/* The message will actually be unreffed when we unlock */
}
if (preallocated == NULL)
return NULL;
- if (connection->link_cache != NULL)
- {
- preallocated->queue_link =
- _dbus_list_pop_first_link (&connection->link_cache);
- preallocated->queue_link->data = NULL;
- }
- else
- {
- preallocated->queue_link = _dbus_list_alloc_link (NULL);
- if (preallocated->queue_link == NULL)
- goto failed_0;
- }
-
- if (connection->link_cache != NULL)
- {
- preallocated->counter_link =
- _dbus_list_pop_first_link (&connection->link_cache);
- preallocated->counter_link->data = connection->outgoing_counter;
- }
- else
- {
- preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
- if (preallocated->counter_link == NULL)
- goto failed_1;
- }
+ preallocated->queue_link = _dbus_list_alloc_link (NULL);
+ if (preallocated->queue_link == NULL)
+ goto failed_0;
+
+ preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
+ if (preallocated->counter_link == NULL)
+ goto failed_1;
_dbus_counter_ref (preallocated->counter_link->data);
DBusMessage *message = element;
DBusConnection *connection = data;
- _dbus_message_remove_counter (message,
- connection->outgoing_counter,
- NULL);
+ _dbus_message_remove_counter (message, connection->outgoing_counter);
dbus_message_unref (message);
}
_dbus_list_free_link (connection->disconnect_message_link);
}
- _dbus_list_clear (&connection->link_cache);
-
_dbus_condvar_free_at_location (&connection->dispatch_cond);
_dbus_condvar_free_at_location (&connection->io_path_cond);
pop_message = _dbus_list_pop_first (&connection->incoming_messages);
_dbus_assert (message == pop_message);
-
+ (void) pop_message; /* unused unless asserting */
+
connection->n_incoming -= 1;
_dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
DBusMessage *message)
{
+ dbus_bool_t sent = FALSE;
+ DBusMessage *ret = NULL;
+ DBusList *expire_link;
+
if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
{
/* This means we're letting the bus route this message */
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- else if (dbus_message_is_method_call (message,
- DBUS_INTERFACE_PEER,
- "Ping"))
+
+ if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ /* Preallocate a linked-list link, so that if we need to dispose of a
+ * message, we can attach it to the expired list */
+ expire_link = _dbus_list_alloc_link (NULL);
+
+ if (!expire_link)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ if (dbus_message_is_method_call (message,
+ DBUS_INTERFACE_PEER,
+ "Ping"))
{
- DBusMessage *ret;
- dbus_bool_t sent;
-
ret = dbus_message_new_method_return (message);
if (ret == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
-
- dbus_message_unref (ret);
+ goto out;
- if (!sent)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
}
else if (dbus_message_is_method_call (message,
DBUS_INTERFACE_PEER,
"GetMachineId"))
{
- DBusMessage *ret;
- dbus_bool_t sent;
DBusString uuid;
ret = dbus_message_new_method_return (message);
if (ret == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto out;
- sent = FALSE;
_dbus_string_init (&uuid);
if (_dbus_get_local_machine_uuid_encoded (&uuid))
{
}
}
_dbus_string_free (&uuid);
-
- dbus_message_unref (ret);
-
- if (!sent)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
}
- else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+ else
{
/* We need to bounce anything else with this interface, otherwise apps
* could start extending the interface and when we added extensions
* here to DBusConnection we'd break those apps.
*/
-
- DBusMessage *ret;
- dbus_bool_t sent;
-
ret = dbus_message_new_error (message,
DBUS_ERROR_UNKNOWN_METHOD,
"Unknown method invoked on org.freedesktop.DBus.Peer interface");
if (ret == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
+ goto out;
+
sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
-
- dbus_message_unref (ret);
-
- if (!sent)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+out:
+ if (ret == NULL)
+ {
+ _dbus_list_free_link (expire_link);
}
else
{
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ /* It'll be safe to unref the reply when we unlock */
+ expire_link->data = ret;
+ _dbus_list_prepend_link (&connection->expired_messages, expire_link);
}
+
+ if (!sent)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
}
/**
DBusMessage *reply;
DBusString str;
DBusPreallocatedSend *preallocated;
+ DBusList *expire_link;
_dbus_verbose (" sending error %s\n",
DBUS_ERROR_UNKNOWN_METHOD);
-
+
if (!_dbus_string_init (&str))
{
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error reply in dispatch\n");
goto out;
}
-
+
+ expire_link = _dbus_list_alloc_link (reply);
+
+ if (expire_link == NULL)
+ {
+ dbus_message_unref (reply);
+ result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ _dbus_verbose ("no memory for error send in dispatch\n");
+ goto out;
+ }
+
preallocated = _dbus_connection_preallocate_send_unlocked (connection);
if (preallocated == NULL)
{
+ _dbus_list_free_link (expire_link);
/* It's OK that this is finalized, because it hasn't been seen by
* anything that could attach user callbacks */
dbus_message_unref (reply);
_dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
reply, NULL);
+ /* reply will be freed when we release the lock */
+ _dbus_list_prepend_link (&connection->expired_messages, expire_link);
- dbus_message_unref (reply);
-
result = DBUS_HANDLER_RESULT_HANDLED;
}
dbus_uint32_t *out_bytes,
dbus_uint32_t *out_fds,
dbus_uint32_t *out_peak_bytes,
- dbus_uint32_t *out_peak_fds,
- dbus_uint32_t *link_cache_size)
+ dbus_uint32_t *out_peak_fds)
{
CONNECTION_LOCK (connection);
if (out_peak_fds != NULL)
*out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
- if (link_cache_size != NULL)
- {
- *link_cache_size = _dbus_list_get_length (&connection->link_cache) * sizeof (DBusList);
- }
-
CONNECTION_UNLOCK (connection);
}
#endif /* DBUS_ENABLE_STATS */