X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-connection.c;h=d987654627b727b406a7203dc5e8de66cb429432;hb=f1ac953748097685a8a7452d9dfe4bdd65192542;hp=648687accb8b2e5d4253d1fed2b8c0fed36fff6b;hpb=636a9a29f89326ca07d5bdbd41d874fa13910c17;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 648687a..d987654 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -44,6 +44,8 @@ #include "dbus-threads-internal.h" #include "dbus-bus.h" #include "dbus-marshal-basic.h" +#include "dbus-transport-kdbus.h" +#include #ifdef DBUS_DISABLE_CHECKS #define TOOK_LOCK_CHECK(connection) @@ -66,22 +68,18 @@ #define CONNECTION_LOCK(connection) do { \ if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \ - _dbus_mutex_lock ((connection)->mutex); \ + _dbus_rmutex_lock ((connection)->mutex); \ TOOK_LOCK_CHECK (connection); \ } while (0) -#define CONNECTION_UNLOCK(connection) do { \ - if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n"); } \ - RELEASING_LOCK_CHECK (connection); \ - _dbus_mutex_unlock ((connection)->mutex); \ - } while (0) +#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection) #define SLOTS_LOCK(connection) do { \ - _dbus_mutex_lock ((connection)->slot_mutex); \ + _dbus_rmutex_lock ((connection)->slot_mutex); \ } while (0) #define SLOTS_UNLOCK(connection) do { \ - _dbus_mutex_unlock ((connection)->slot_mutex); \ + _dbus_rmutex_unlock ((connection)->slot_mutex); \ } while (0) #define DISPATCH_STATUS_NAME(s) \ @@ -207,6 +205,27 @@ * @{ */ +#ifdef DBUS_ENABLE_VERBOSE_MODE +static void +_dbus_connection_trace_ref (DBusConnection *connection, + int old_refcount, + int new_refcount, + const char *why) +{ + static int enabled = -1; + + _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount, + why, "DBUS_CONNECTION_TRACE", &enabled); +} +#else +#define _dbus_connection_trace_ref(c,o,n,w) \ + do \ + {\ + (void) (o); \ + (void) (n); \ + } while (0) +#endif + /** * Internal struct representing a message filter function */ @@ -247,15 +266,16 @@ struct DBusConnection { DBusAtomic refcount; /**< Reference count. */ - DBusMutex *mutex; /**< Lock on the entire DBusConnection */ + DBusRMutex *mutex; /**< Lock on the entire DBusConnection */ - DBusMutex *dispatch_mutex; /**< Protects dispatch_acquired */ + DBusCMutex *dispatch_mutex; /**< Protects dispatch_acquired */ DBusCondVar *dispatch_cond; /**< Notify when dispatch_acquired is available */ - DBusMutex *io_path_mutex; /**< Protects io_path_acquired */ + DBusCMutex *io_path_mutex; /**< Protects io_path_acquired */ DBusCondVar *io_path_cond; /**< Notify when io_path_acquired is available */ DBusList *outgoing_messages; /**< Queue of messages we need to send, send the end of the list first. */ DBusList *incoming_messages; /**< Queue of messages we have received, end of the list received most recently. */ + DBusList *expired_messages; /**< Messages that will be released when we next unlock. */ DBusMessage *message_borrowed; /**< Filled in if the first incoming message has been borrowed; * dispatch_acquired will be set by the borrower @@ -272,7 +292,7 @@ struct DBusConnection DBusList *filter_list; /**< List of filters. */ - DBusMutex *slot_mutex; /**< Lock on slot_list so overall connection lock need not be taken */ + DBusRMutex *slot_mutex; /**< Lock on slot_list so overall connection lock need not be taken */ DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */ DBusHashTable *pending_replies; /**< Hash of message serials to #DBusPendingCall. */ @@ -290,9 +310,6 @@ struct DBusConnection 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 */ @@ -342,8 +359,14 @@ static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DB static DBusMessageFilter * _dbus_message_filter_ref (DBusMessageFilter *filter) { - _dbus_assert (filter->refcount.value > 0); +#ifdef DBUS_DISABLE_ASSERT _dbus_atomic_inc (&filter->refcount); +#else + dbus_int32_t old_value; + + old_value = _dbus_atomic_inc (&filter->refcount); + _dbus_assert (old_value > 0); +#endif return filter; } @@ -351,9 +374,12 @@ _dbus_message_filter_ref (DBusMessageFilter *filter) static void _dbus_message_filter_unref (DBusMessageFilter *filter) { - _dbus_assert (filter->refcount.value > 0); + dbus_int32_t old_value; + + old_value = _dbus_atomic_dec (&filter->refcount); + _dbus_assert (old_value > 0); - if (_dbus_atomic_dec (&filter->refcount) == 1) + if (old_value == 1) { if (filter->free_user_data_function) (* filter->free_user_data_function) (filter->user_data); @@ -381,7 +407,31 @@ _dbus_connection_lock (DBusConnection *connection) void _dbus_connection_unlock (DBusConnection *connection) { - CONNECTION_UNLOCK (connection); + DBusList *expired_messages; + DBusList *iter; + + if (TRACE_LOCKS) + { + _dbus_verbose ("UNLOCK\n"); + } + + /* If we had messages that expired (fell off the incoming or outgoing + * queues) while we were locked, actually release them now */ + expired_messages = connection->expired_messages; + connection->expired_messages = NULL; + + RELEASING_LOCK_CHECK (connection); + _dbus_rmutex_unlock (connection->mutex); + + for (iter = _dbus_list_pop_first_link (&expired_messages); + iter != NULL; + iter = _dbus_list_pop_first_link (&expired_messages)) + { + DBusMessage *message = iter->data; + + dbus_message_unref (message); + _dbus_list_free_link (iter); + } } /** @@ -399,32 +449,6 @@ _dbus_connection_wakeup_mainloop (DBusConnection *connection) } #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 * @@ -445,9 +469,9 @@ _dbus_connection_test_get_locks (DBusConnection *connection, DBusCondVar **dispatch_cond_loc, DBusCondVar **io_path_cond_loc) { - *mutex_loc = connection->mutex; - *dispatch_mutex_loc = connection->dispatch_mutex; - *io_path_mutex_loc = connection->io_path_mutex; + *mutex_loc = (DBusMutex *) connection->mutex; + *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex; + *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex; *dispatch_cond_loc = connection->dispatch_cond; *io_path_cond_loc = connection->io_path_cond; } @@ -512,7 +536,11 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, dbus_message_get_signature (message), dbus_message_get_reply_serial (message), connection, - connection->n_incoming);} + connection->n_incoming); + + _dbus_message_trace_ref (message, -1, -1, + "_dbus_conection_queue_received_message_link"); +} /** * Adds a link + message to the incoming message queue. @@ -533,7 +561,10 @@ _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, connection->n_incoming += 1; _dbus_connection_wakeup_mainloop (connection); - + + _dbus_message_trace_ref (link->data, -1, -1, + "_dbus_connection_queue_synthesized_message_link"); + _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", link->data, connection, connection->n_incoming); } @@ -600,8 +631,8 @@ _dbus_connection_get_message_to_send (DBusConnection *connection) * @param message the message that was sent. */ void -_dbus_connection_message_sent (DBusConnection *connection, - DBusMessage *message) +_dbus_connection_message_sent_unlocked (DBusConnection *connection, + DBusMessage *message) { DBusList *link; @@ -616,11 +647,10 @@ _dbus_connection_message_sent (DBusConnection *connection, _dbus_assert (link != NULL); _dbus_assert (link->data == message); - /* Save this link in the link cache */ _dbus_list_unlink (&connection->outgoing_messages, link); - _dbus_list_prepend_link (&connection->link_cache, link); - + _dbus_list_prepend_link (&connection->expired_messages, link); + connection->n_outgoing -= 1; _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", @@ -638,12 +668,11 @@ _dbus_connection_message_sent (DBusConnection *connection, dbus_message_get_signature (message), connection, connection->n_outgoing); - /* Save this link in the link cache also */ - _dbus_message_remove_counter (message, connection->outgoing_counter, - &link); - _dbus_list_prepend_link (&connection->link_cache, link); - - dbus_message_unref (message); + /* 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); + + /* The message will actually be unreffed when we unlock */ } /** Function to be called in protected_change_watch() with refcount held */ @@ -1052,7 +1081,7 @@ _dbus_connection_acquire_io_path (DBusConnection *connection, CONNECTION_UNLOCK (connection); _dbus_verbose ("locking io_path_mutex\n"); - _dbus_mutex_lock (connection->io_path_mutex); + _dbus_cmutex_lock (connection->io_path_mutex); _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n", connection->io_path_acquired, timeout_milliseconds); @@ -1101,7 +1130,7 @@ _dbus_connection_acquire_io_path (DBusConnection *connection, connection->io_path_acquired, we_acquired); _dbus_verbose ("unlocking io_path_mutex\n"); - _dbus_mutex_unlock (connection->io_path_mutex); + _dbus_cmutex_unlock (connection->io_path_mutex); CONNECTION_LOCK (connection); @@ -1125,7 +1154,7 @@ _dbus_connection_release_io_path (DBusConnection *connection) HAVE_LOCK_CHECK (connection); _dbus_verbose ("locking io_path_mutex\n"); - _dbus_mutex_lock (connection->io_path_mutex); + _dbus_cmutex_lock (connection->io_path_mutex); _dbus_assert (connection->io_path_acquired); @@ -1136,7 +1165,7 @@ _dbus_connection_release_io_path (DBusConnection *connection) _dbus_condvar_wake_one (connection->io_path_cond); _dbus_verbose ("unlocking io_path_mutex\n"); - _dbus_mutex_unlock (connection->io_path_mutex); + _dbus_cmutex_unlock (connection->io_path_mutex); } /** @@ -1265,15 +1294,15 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (connection == NULL) goto error; - _dbus_mutex_new_at_location (&connection->mutex); + _dbus_rmutex_new_at_location (&connection->mutex); if (connection->mutex == NULL) goto error; - _dbus_mutex_new_at_location (&connection->io_path_mutex); + _dbus_cmutex_new_at_location (&connection->io_path_mutex); if (connection->io_path_mutex == NULL) goto error; - _dbus_mutex_new_at_location (&connection->dispatch_mutex); + _dbus_cmutex_new_at_location (&connection->dispatch_mutex); if (connection->dispatch_mutex == NULL) goto error; @@ -1285,7 +1314,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (connection->io_path_cond == NULL) goto error; - _dbus_mutex_new_at_location (&connection->slot_mutex); + _dbus_rmutex_new_at_location (&connection->slot_mutex); if (connection->slot_mutex == NULL) goto error; @@ -1310,8 +1339,9 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (_dbus_modify_sigpipe) _dbus_disable_sigpipe (); - - connection->refcount.value = 1; + + /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */ + _dbus_atomic_inc (&connection->refcount); connection->transport = transport; connection->watches = watch_list; connection->timeouts = timeout_list; @@ -1348,7 +1378,8 @@ _dbus_connection_new_for_transport (DBusTransport *transport) _dbus_transport_ref (transport); CONNECTION_UNLOCK (connection); - + + _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport"); return connection; error: @@ -1362,10 +1393,10 @@ _dbus_connection_new_for_transport (DBusTransport *transport) { _dbus_condvar_free_at_location (&connection->io_path_cond); _dbus_condvar_free_at_location (&connection->dispatch_cond); - _dbus_mutex_free_at_location (&connection->mutex); - _dbus_mutex_free_at_location (&connection->io_path_mutex); - _dbus_mutex_free_at_location (&connection->dispatch_mutex); - _dbus_mutex_free_at_location (&connection->slot_mutex); + _dbus_rmutex_free_at_location (&connection->mutex); + _dbus_cmutex_free_at_location (&connection->io_path_mutex); + _dbus_cmutex_free_at_location (&connection->dispatch_mutex); + _dbus_rmutex_free_at_location (&connection->slot_mutex); dbus_free (connection); } if (pending_replies) @@ -1395,13 +1426,17 @@ _dbus_connection_new_for_transport (DBusTransport *transport) */ DBusConnection * _dbus_connection_ref_unlocked (DBusConnection *connection) -{ +{ + dbus_int32_t old_refcount; + _dbus_assert (connection != NULL); _dbus_assert (connection->generation == _dbus_current_generation); HAVE_LOCK_CHECK (connection); - _dbus_atomic_inc (&connection->refcount); + old_refcount = _dbus_atomic_inc (&connection->refcount); + _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1, + "ref_unlocked"); return connection; } @@ -1415,15 +1450,18 @@ _dbus_connection_ref_unlocked (DBusConnection *connection) void _dbus_connection_unref_unlocked (DBusConnection *connection) { - dbus_bool_t last_unref; + dbus_int32_t old_refcount; HAVE_LOCK_CHECK (connection); - + _dbus_assert (connection != NULL); - last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); + old_refcount = _dbus_atomic_dec (&connection->refcount); + + _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1, + "unref_unlocked"); - if (last_unref) + if (old_refcount == 1) _dbus_connection_last_unref (connection); } @@ -1495,7 +1533,7 @@ _dbus_connection_handle_watch (DBusWatch *watch, return retval; } -_DBUS_DEFINE_GLOBAL_LOCK (shared_connections); +/* Protected by _DBUS_LOCK (shared_connections) */ static DBusHashTable *shared_connections = NULL; static DBusList *shared_connections_no_guid = NULL; @@ -1519,9 +1557,14 @@ static void shared_connections_shutdown (void *data) { int n_entries; - - _DBUS_LOCK (shared_connections); - + + if (!_DBUS_LOCK (shared_connections)) + { + /* We'd have initialized locks before adding anything, so there + * can't be anything there. */ + return; + } + /* This is a little bit unpleasant... better ideas? */ while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) { @@ -1535,7 +1578,8 @@ shared_connections_shutdown (void *data) _DBUS_UNLOCK (shared_connections); close_connection_on_shutdown (connection); - _DBUS_LOCK (shared_connections); + if (!_DBUS_LOCK (shared_connections)) + _dbus_assert_not_reached ("global locks were already initialized"); /* The connection should now be dead and not in our hash ... */ _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); @@ -1554,7 +1598,8 @@ shared_connections_shutdown (void *data) { _DBUS_UNLOCK (shared_connections); close_connection_on_shutdown (connection); - _DBUS_LOCK (shared_connections); + if (!_DBUS_LOCK (shared_connections)) + _dbus_assert_not_reached ("global locks were already initialized"); connection = _dbus_list_pop_first (&shared_connections_no_guid); } } @@ -1571,8 +1616,13 @@ connection_lookup_shared (DBusAddressEntry *entry, _dbus_verbose ("checking for existing connection\n"); *result = NULL; - - _DBUS_LOCK (shared_connections); + + if (!_DBUS_LOCK (shared_connections)) + { + /* If it was shared, we'd have initialized global locks when we put + * it in shared_connections. */ + return FALSE; + } if (shared_connections == NULL) { @@ -1670,7 +1720,8 @@ connection_record_shared_unlocked (DBusConnection *connection, if (guid == NULL) { - _DBUS_LOCK (shared_connections); + if (!_DBUS_LOCK (shared_connections)) + return FALSE; if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) { @@ -1697,8 +1748,14 @@ connection_record_shared_unlocked (DBusConnection *connection, dbus_free (guid_key); return FALSE; } - - _DBUS_LOCK (shared_connections); + + if (!_DBUS_LOCK (shared_connections)) + { + dbus_free (guid_in_connection); + dbus_free (guid_key); + return FALSE; + } + _dbus_assert (shared_connections != NULL); if (!_dbus_hash_table_insert_string (shared_connections, @@ -1729,9 +1786,14 @@ connection_forget_shared_unlocked (DBusConnection *connection) if (!connection->shareable) return; - - _DBUS_LOCK (shared_connections); - + + if (!_DBUS_LOCK (shared_connections)) + { + /* If it was shared, we'd have initialized global locks when we put + * it in the table; so it can't be there. */ + return; + } + if (connection->server_guid != NULL) { _dbus_verbose ("dropping connection to %s out of the shared table\n", @@ -1783,6 +1845,7 @@ connection_try_from_address_entry (DBusAddressEntry *entry, #ifndef DBUS_DISABLE_CHECKS _dbus_assert (!connection->have_connection_lock); #endif + return connection; } @@ -1914,31 +1977,13 @@ _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 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); @@ -1967,6 +2012,8 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *con _dbus_list_prepend_link (&connection->outgoing_messages, preallocated->queue_link); + /* It's OK that we'll never call the notify function, because for the + * outgoing limit, there isn't one */ _dbus_message_add_counter_link (message, preallocated->counter_link); @@ -2012,6 +2059,23 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *con _dbus_verbose ("Message %p serial is %u\n", message, dbus_message_get_serial (message)); + if(dbus_transport_is_kdbus(connection)) + { + const char* name; + char* sender; + + name = dbus_bus_get_unique_name(connection); + sender = malloc (strlen(name) + 4); + if(sender) + { + strcpy(sender,":1."); + strcpy(&sender[3], name); + _dbus_verbose ("Message sender: %s\n", sender); + dbus_message_set_sender(message, sender); + free((void*)sender); + } + } + dbus_message_lock (message); /* Now we need to run an iteration to hopefully just write the messages @@ -2108,23 +2172,15 @@ _dbus_connection_send_and_unlock (DBusConnection *connection, void _dbus_connection_close_if_only_one_ref (DBusConnection *connection) { - dbus_int32_t tmp_refcount; + dbus_int32_t refcount; CONNECTION_LOCK (connection); - /* We increment and then decrement the refcount, because there is no - * _dbus_atomic_get (mirroring the fact that there's no InterlockedGet - * on Windows). */ - _dbus_atomic_inc (&connection->refcount); - tmp_refcount = _dbus_atomic_dec (&connection->refcount); - - /* The caller should have one ref, and this function temporarily took - * one more, which is reflected in this count even though we already - * released it (relying on the caller's ref) due to _dbus_atomic_dec - * semantics */ - _dbus_assert (tmp_refcount >= 2); + refcount = _dbus_atomic_get (&connection->refcount); + /* The caller should have at least one ref */ + _dbus_assert (refcount >= 1); - if (tmp_refcount == 2) + if (refcount == 1) _dbus_connection_close_possibly_shared_and_unlock (connection); else CONNECTION_UNLOCK (connection); @@ -2376,7 +2432,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending) * below */ timeout = _dbus_pending_call_get_timeout_unlocked (pending); - _dbus_get_current_time (&start_tv_sec, &start_tv_usec); + _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec); if (timeout) { timeout_milliseconds = dbus_timeout_get_interval (timeout); @@ -2433,7 +2489,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending) return; } - _dbus_get_current_time (&tv_sec, &tv_usec); + _dbus_get_monotonic_time (&tv_sec, &tv_usec); elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000; @@ -2624,10 +2680,13 @@ dbus_connection_open_private (const char *address, DBusConnection * dbus_connection_ref (DBusConnection *connection) { + dbus_int32_t old_refcount; + _dbus_return_val_if_fail (connection != NULL, NULL); _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); - - _dbus_atomic_inc (&connection->refcount); + old_refcount = _dbus_atomic_inc (&connection->refcount); + _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1, + "ref"); return connection; } @@ -2639,9 +2698,7 @@ free_outgoing_message (void *element, 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); } @@ -2655,9 +2712,9 @@ _dbus_connection_last_unref (DBusConnection *connection) DBusList *link; _dbus_verbose ("Finalizing connection %p\n", connection); - - _dbus_assert (connection->refcount.value == 0); - + + _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0); + /* You have to disconnect the connection before unref:ing it. Otherwise * you won't get the disconnected message. */ @@ -2723,17 +2780,15 @@ _dbus_connection_last_unref (DBusConnection *connection) _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); - _dbus_mutex_free_at_location (&connection->io_path_mutex); - _dbus_mutex_free_at_location (&connection->dispatch_mutex); + _dbus_cmutex_free_at_location (&connection->io_path_mutex); + _dbus_cmutex_free_at_location (&connection->dispatch_mutex); - _dbus_mutex_free_at_location (&connection->slot_mutex); + _dbus_rmutex_free_at_location (&connection->slot_mutex); - _dbus_mutex_free_at_location (&connection->mutex); + _dbus_rmutex_free_at_location (&connection->mutex); dbus_free (connection); } @@ -2760,14 +2815,17 @@ _dbus_connection_last_unref (DBusConnection *connection) void dbus_connection_unref (DBusConnection *connection) { - dbus_bool_t last_unref; + dbus_int32_t old_refcount; _dbus_return_if_fail (connection != NULL); _dbus_return_if_fail (connection->generation == _dbus_current_generation); - last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); + old_refcount = _dbus_atomic_dec (&connection->refcount); + + _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1, + "unref"); - if (last_unref) + if (old_refcount == 1) { #ifndef DBUS_DISABLE_CHECKS if (_dbus_transport_get_is_connected (connection->transport)) @@ -2947,6 +3005,24 @@ dbus_connection_get_is_authenticated (DBusConnection *connection) } /** + * Sets authenticated status for connection. Needed for kdbus, where authentication is + * made in different manner. + * + * @param connection the connection + */ +dbus_bool_t +dbus_connection_set_is_authenticated (DBusConnection *connection) +{ + _dbus_return_val_if_fail (connection != NULL, FALSE); + + CONNECTION_LOCK (connection); + connection->transport->authenticated = TRUE; + CONNECTION_UNLOCK (connection); + + return TRUE; +} + +/** * Gets whether the connection is not authenticated as a specific * user. If the connection is not authenticated, this function * returns #TRUE, and if it is authenticated but as an anonymous user, @@ -3823,6 +3899,8 @@ dbus_connection_borrow_message (DBusConnection *connection) CONNECTION_UNLOCK (connection); + _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message"); + /* We don't update dispatch status until it's returned or stolen */ return message; @@ -3857,6 +3935,8 @@ dbus_connection_return_message (DBusConnection *connection, status = _dbus_connection_get_dispatch_status_unlocked (connection); _dbus_connection_update_dispatch_status_and_unlock (connection, status); + + _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message"); } /** @@ -3886,7 +3966,8 @@ dbus_connection_steal_borrowed_message (DBusConnection *connection, 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", @@ -3898,6 +3979,8 @@ dbus_connection_steal_borrowed_message (DBusConnection *connection, status = _dbus_connection_get_dispatch_status_unlocked (connection); _dbus_connection_update_dispatch_status_and_unlock (connection, status); + _dbus_message_trace_ref (message, -1, -1, + "dbus_connection_steal_borrowed_message"); } /* See dbus_connection_pop_message, but requires the caller to own @@ -3932,6 +4015,9 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) dbus_message_get_signature (link->data), connection, connection->n_incoming); + _dbus_message_trace_ref (link->data, -1, -1, + "_dbus_connection_pop_message_link_unlocked"); + check_disconnected_message_arrived_unlocked (connection, link->data); return link; @@ -3993,6 +4079,9 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, "no member", dbus_message_get_signature (message_link->data), connection, connection->n_incoming); + + _dbus_message_trace_ref (message_link->data, -1, -1, + "_dbus_connection_putback_message_link_unlocked"); } /** @@ -4061,7 +4150,7 @@ _dbus_connection_acquire_dispatch (DBusConnection *connection) CONNECTION_UNLOCK (connection); _dbus_verbose ("locking dispatch_mutex\n"); - _dbus_mutex_lock (connection->dispatch_mutex); + _dbus_cmutex_lock (connection->dispatch_mutex); while (connection->dispatch_acquired) { @@ -4075,7 +4164,7 @@ _dbus_connection_acquire_dispatch (DBusConnection *connection) connection->dispatch_acquired = TRUE; _dbus_verbose ("unlocking dispatch_mutex\n"); - _dbus_mutex_unlock (connection->dispatch_mutex); + _dbus_cmutex_unlock (connection->dispatch_mutex); CONNECTION_LOCK (connection); _dbus_connection_unref_unlocked (connection); @@ -4094,7 +4183,7 @@ _dbus_connection_release_dispatch (DBusConnection *connection) HAVE_LOCK_CHECK (connection); _dbus_verbose ("locking dispatch_mutex\n"); - _dbus_mutex_lock (connection->dispatch_mutex); + _dbus_cmutex_lock (connection->dispatch_mutex); _dbus_assert (connection->dispatch_acquired); @@ -4102,7 +4191,7 @@ _dbus_connection_release_dispatch (DBusConnection *connection) _dbus_condvar_wake_one (connection->dispatch_cond); _dbus_verbose ("unlocking dispatch_mutex\n"); - _dbus_mutex_unlock (connection->dispatch_mutex); + _dbus_cmutex_unlock (connection->dispatch_mutex); } static void @@ -4141,7 +4230,7 @@ notify_disconnected_unlocked (DBusConnection *connection) while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) { - _dbus_connection_message_sent (connection, link->data); + _dbus_connection_message_sent_unlocked (connection, link->data); } } } @@ -4178,7 +4267,7 @@ static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) { HAVE_LOCK_CHECK (connection); - + if (connection->n_incoming > 0) return DBUS_DISPATCH_DATA_REMAINS; else if (!_dbus_transport_queue_messages (connection->transport)) @@ -4187,7 +4276,7 @@ _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) { DBusDispatchStatus status; dbus_bool_t is_connected; - + status = _dbus_transport_get_dispatch_status (connection->transport); is_connected = _dbus_transport_get_is_connected (connection->transport); @@ -4326,44 +4415,48 @@ static DBusHandlerResult _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)) { @@ -4376,43 +4469,38 @@ _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, } } _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; } /** @@ -4660,10 +4748,11 @@ dbus_connection_dispatch (DBusConnection *connection) 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; @@ -4694,11 +4783,24 @@ dbus_connection_dispatch (DBusConnection *connection) _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); result = DBUS_HANDLER_RESULT_NEED_MEMORY; _dbus_verbose ("no memory for error send in dispatch\n"); @@ -4707,9 +4809,9 @@ dbus_connection_dispatch (DBusConnection *connection) _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; } @@ -4735,20 +4837,35 @@ dbus_connection_dispatch (DBusConnection *connection) */ _dbus_connection_putback_message_link_unlocked (connection, message_link); + /* now we don't want to free them */ + message_link = NULL; + message = NULL; } else { _dbus_verbose (" ... done dispatching\n"); - - _dbus_list_free_link (message_link); - dbus_message_unref (message); /* don't want the message to count in max message limits - * in computing dispatch status below - */ } - + _dbus_connection_release_dispatch (connection); HAVE_LOCK_CHECK (connection); + if (message != NULL) + { + /* We don't want this message to count in maximum message limits when + * computing the dispatch status, below. We have to drop the lock + * temporarily, because finalizing a message can trigger callbacks. + * + * We have a reference to the connection, and we don't use any cached + * pointers to the connection's internals below this point, so it should + * be safe to drop the lock and take it back. */ + CONNECTION_UNLOCK (connection); + dbus_message_unref (message); + CONNECTION_LOCK (connection); + } + + if (message_link != NULL) + _dbus_list_free_link (message_link); + _dbus_verbose ("before final status update\n"); status = _dbus_connection_get_dispatch_status_unlocked (connection); @@ -5420,8 +5537,8 @@ dbus_connection_add_filter (DBusConnection *connection, if (filter == NULL) return FALSE; - filter->refcount.value = 1; - + _dbus_atomic_inc (&filter->refcount); + CONNECTION_LOCK (connection); if (!_dbus_list_append (&connection->filter_list, @@ -5512,10 +5629,13 @@ dbus_connection_remove_filter (DBusConnection *connection, } /** - * Registers a handler for a given path in the object hierarchy. - * The given vtable handles messages sent to exactly the given path. + * Registers a handler for a given path or subsection in the object + * hierarchy. The given vtable handles messages sent to exactly the + * given path or also for paths bellow that, depending on fallback + * parameter. * * @param connection the connection + * @param fallback whether to handle messages also for "subdirectory" * @param path a '/' delimited string of path elements * @param vtable the virtual table * @param user_data data to pass to functions in the vtable @@ -5523,20 +5643,16 @@ dbus_connection_remove_filter (DBusConnection *connection, * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or * #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported */ -dbus_bool_t -dbus_connection_try_register_object_path (DBusConnection *connection, - const char *path, - const DBusObjectPathVTable *vtable, - void *user_data, - DBusError *error) +static dbus_bool_t +_dbus_connection_register_object_path (DBusConnection *connection, + dbus_bool_t fallback, + const char *path, + const DBusObjectPathVTable *vtable, + void *user_data, + DBusError *error) { char **decomposed_path; dbus_bool_t retval; - - _dbus_return_val_if_fail (connection != NULL, FALSE); - _dbus_return_val_if_fail (path != NULL, FALSE); - _dbus_return_val_if_fail (path[0] == '/', FALSE); - _dbus_return_val_if_fail (vtable != NULL, FALSE); if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) return FALSE; @@ -5544,7 +5660,7 @@ dbus_connection_try_register_object_path (DBusConnection *connectio CONNECTION_LOCK (connection); retval = _dbus_object_tree_register (connection->objects, - FALSE, + fallback, (const char **) decomposed_path, vtable, user_data, error); @@ -5559,6 +5675,33 @@ dbus_connection_try_register_object_path (DBusConnection *connectio * Registers a handler for a given path in the object hierarchy. * The given vtable handles messages sent to exactly the given path. * + * @param connection the connection + * @param path a '/' delimited string of path elements + * @param vtable the virtual table + * @param user_data data to pass to functions in the vtable + * @param error address where an error can be returned + * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or + * #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported + */ +dbus_bool_t +dbus_connection_try_register_object_path (DBusConnection *connection, + const char *path, + const DBusObjectPathVTable *vtable, + void *user_data, + DBusError *error) +{ + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (path != NULL, FALSE); + _dbus_return_val_if_fail (path[0] == '/', FALSE); + _dbus_return_val_if_fail (vtable != NULL, FALSE); + + return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error); +} + +/** + * Registers a handler for a given path in the object hierarchy. + * The given vtable handles messages sent to exactly the given path. + * * It is a bug to call this function for object paths which already * have a handler. Use dbus_connection_try_register_object_path() if this * might be the case. @@ -5576,7 +5719,6 @@ dbus_connection_register_object_path (DBusConnection *connection, const DBusObjectPathVTable *vtable, void *user_data) { - char **decomposed_path; dbus_bool_t retval; DBusError error = DBUS_ERROR_INIT; @@ -5585,19 +5727,7 @@ dbus_connection_register_object_path (DBusConnection *connection, _dbus_return_val_if_fail (path[0] == '/', FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); - if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) - return FALSE; - - CONNECTION_LOCK (connection); - - retval = _dbus_object_tree_register (connection->objects, - FALSE, - (const char **) decomposed_path, vtable, - user_data, &error); - - CONNECTION_UNLOCK (connection); - - dbus_free_string_array (decomposed_path); + retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error); if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) { @@ -5630,29 +5760,12 @@ dbus_connection_try_register_fallback (DBusConnection *connection, void *user_data, DBusError *error) { - char **decomposed_path; - dbus_bool_t retval; - _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (path != NULL, FALSE); _dbus_return_val_if_fail (path[0] == '/', FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); - if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) - return FALSE; - - CONNECTION_LOCK (connection); - - retval = _dbus_object_tree_register (connection->objects, - TRUE, - (const char **) decomposed_path, vtable, - user_data, error); - - CONNECTION_UNLOCK (connection); - - dbus_free_string_array (decomposed_path); - - return retval; + return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error); } /** @@ -5678,7 +5791,6 @@ dbus_connection_register_fallback (DBusConnection *connection, const DBusObjectPathVTable *vtable, void *user_data) { - char **decomposed_path; dbus_bool_t retval; DBusError error = DBUS_ERROR_INIT; @@ -5687,19 +5799,7 @@ dbus_connection_register_fallback (DBusConnection *connection, _dbus_return_val_if_fail (path[0] == '/', FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); - if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) - return FALSE; - - CONNECTION_LOCK (connection); - - retval = _dbus_object_tree_register (connection->objects, - TRUE, - (const char **) decomposed_path, vtable, - user_data, &error); - - CONNECTION_UNLOCK (connection); - - dbus_free_string_array (decomposed_path); + retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error); if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) { @@ -5814,8 +5914,8 @@ dbus_connection_list_registered (DBusConnection *connection, return retval; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (connection_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -5835,7 +5935,6 @@ dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (connection_slots), slot_p); } @@ -5936,7 +6035,8 @@ dbus_connection_get_data (DBusConnection *connection, void *res; _dbus_return_val_if_fail (connection != NULL, NULL); - + _dbus_return_val_if_fail (slot >= 0, NULL); + SLOTS_LOCK (connection); res = _dbus_data_slot_list_get (&slot_allocator, @@ -6171,8 +6271,7 @@ _dbus_connection_get_stats (DBusConnection *connection, 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); @@ -6197,11 +6296,6 @@ _dbus_connection_get_stats (DBusConnection *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 */ @@ -6226,4 +6320,25 @@ dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) return res; } +/** + * Returns the address of the transport object of this connection + * + * @param connection the connection + * @returns the address string + */ +const char* +_dbus_connection_get_address (DBusConnection *connection) +{ + return _dbus_transport_get_address (connection->transport); +} + +DBusTransport* +dbus_connection_get_transport(DBusConnection *connection) +{ + _dbus_return_val_if_fail (connection != NULL, NULL); + + return connection->transport; +} + + /** @} */