diff options
author | Havoc Pennington <hp@redhat.com> | 2003-03-16 08:08:21 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2003-03-16 08:08:21 +0000 |
commit | ce173b29fc1e9432cb5956952afdbe775da12415 (patch) | |
tree | bafd96156eba1879568131fe97789e60fd7e6062 /dbus/dbus-bus.c | |
parent | f587ce7845edb0eb01451368d01b5bc86b5904cd (diff) | |
download | dbus-ce173b29fc1e9432cb5956952afdbe775da12415.tar.gz |
2003-03-16 Havoc Pennington <hp@pobox.com>
Oops - test code was only testing failure of around 30 of the
mallocs in the test path, but it turns out there are 500+
mallocs. I believe this was due to misguided linking setup such
that there was one copy of dbus_malloc etc. in the daemon and one
in the shared lib, and only daemon mallocs were tested. In any
case, the test case now tests all 500+ mallocs, and doesn't pass
yet, though there are lots of fixes in this patch.
* dbus/dbus-connection.c (dbus_connection_dispatch_message): fix
this so that it doesn't need to allocate memory, since it
has no way of indicating failure due to OOM (and would be
annoying if it did).
* dbus/dbus-list.c (_dbus_list_pop_first_link): new function
* bus/Makefile.am: rearrange to create two self-contained
libraries, to avoid having libraries with overlapping symbols.
that was resulting in weirdness, e.g. I'm pretty sure there
were two copies of global static variables.
* dbus/dbus-internals.c: move the malloc debug stuff to
dbus-memory.c
* dbus/dbus-list.c (free_link): free list mempool if it becomes
empty.
* dbus/dbus-memory.c (_dbus_disable_mem_pools): new function
* dbus/dbus-address.c (dbus_parse_address): free list nodes
on failure.
* bus/dispatch.c (bus_dispatch_add_connection): free
message_handler_slot when no longer using it, so
memory leak checkers are happy for the test suite.
* dbus/dbus-server-debug-pipe.c (debug_finalize): free server name
* bus/bus.c (new_connection_callback): disconnect in here if
bus_connections_setup_connection fails.
* bus/connection.c (bus_connections_unref): fix to free the
connections
(bus_connections_setup_connection): if this fails, don't
disconnect the connection, just be sure there are no side
effects.
* dbus/dbus-string.c (undo_alignment): unbreak this
* dbus/dbus-auth.c (_dbus_auth_unref): free some stuff we were
leaking
(_dbus_auth_new): fix the order in which we free strings
on OOM failure
* bus/connection.c (bus_connection_disconnected): fix to
not send ServiceDeleted multiple times in case of memory
allocation failure
* dbus/dbus-bus.c (dbus_bus_get_base_service): new function to
get the base service name
(dbus_bus_register_client): don't return base service name,
instead store it on the DBusConnection and have an accessor
function for it.
(dbus_bus_register_client): rename dbus_bus_register()
* bus/dispatch.c (check_hello_message): verify that other
connections on the bus also got the correct results, not
just the one sending hello
Diffstat (limited to 'dbus/dbus-bus.c')
-rw-r--r-- | dbus/dbus-bus.c | 218 |
1 files changed, 210 insertions, 8 deletions
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index cc612a78..3e409257 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -31,26 +31,177 @@ * @ingroup DBus * @brief Functions for communicating with the message bus * + */ + + +/** + * @defgroup DBusBusInternals Message bus APIs internals + * @ingroup DBusInternals + * @brief Internals of functions for communicating with the message bus + * + * @{ + */ + +/** + * Block of message-bus-related data we attach to each + * #DBusConnection used with these convenience functions. + * + */ +typedef struct +{ + char *base_service; + +} BusData; + +/** The slot we have reserved to store BusData + */ +static int bus_data_slot = -1; +/** Number of connections using the slot + */ +static int bus_data_slot_refcount = 0; + +/** + * Lock for bus_data_slot and bus_data_slot_refcount + */ +static DBusMutex *slot_lock; + +/** + * Initialize the mutex used for bus_data_slot + * + * @returns the mutex + */ +DBusMutex * +_dbus_bus_init_lock (void) +{ + slot_lock = dbus_mutex_new (); + return slot_lock; +} + +static dbus_bool_t +data_slot_ref (void) +{ + dbus_mutex_lock (slot_lock); + + if (bus_data_slot < 0) + bus_data_slot = dbus_connection_allocate_data_slot (); + + if (bus_data_slot < 0) + { + dbus_mutex_unlock (slot_lock); + return FALSE; + } + + bus_data_slot_refcount += 1; + + dbus_mutex_unlock (slot_lock); + + return TRUE; +} + +static void +data_slot_unref (void) +{ + dbus_mutex_lock (slot_lock); + + _dbus_assert (bus_data_slot >= 0); + _dbus_assert (bus_data_slot_refcount > 0); + + bus_data_slot_refcount -= 1; + + if (bus_data_slot_refcount == 0) + { + dbus_connection_free_data_slot (bus_data_slot); + bus_data_slot = -1; + } + + dbus_mutex_unlock (slot_lock); +} + +static void +bus_data_free (void *data) +{ + BusData *bd = data; + + dbus_free (bd->base_service); + dbus_free (bd); + + data_slot_unref (); +} + +static BusData* +ensure_bus_data (DBusConnection *connection) +{ + BusData *bd; + + if (!data_slot_ref ()) + return NULL; + + bd = dbus_connection_get_data (connection, bus_data_slot); + if (bd == NULL) + { + bd = dbus_new0 (BusData, 1); + if (bd == NULL) + { + data_slot_unref (); + return NULL; + } + + dbus_connection_set_data (connection, bus_data_slot, bd, + bus_data_free); + + /* Data slot refcount now held by the BusData */ + } + else + { + data_slot_unref (); + } + + return bd; +} + +/** @} */ /* end of implementation details docs */ + +/** + * @addtogroup DBusBus * @{ */ /** * Registers a connection with the bus. This must be the first * thing an application does when connecting to the message bus. + * If registration succeeds, the base service name will be set, + * and can be obtained using dbus_bus_get_base_service(). * * @todo if we get an error reply, it has to be converted into * DBusError and returned * * @param connection the connection * @param error place to store errors - * @returns the client's unique service name, #NULL on error + * @returns #TRUE on success */ -char* -dbus_bus_register_client (DBusConnection *connection, - DBusError *error) +dbus_bool_t +dbus_bus_register (DBusConnection *connection, + DBusError *error) { DBusMessage *message, *reply; char *name; + BusData *bd; + + bd = ensure_bus_data (connection); + if (bd == NULL) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + if (bd->base_service != NULL) + { + _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n"); + /* This isn't an error, it's a programming bug. We'll be nice + * and not _dbus_assert_not_reached() + */ + return TRUE; + } message = dbus_message_new (DBUS_SERVICE_DBUS, DBUS_MESSAGE_HELLO); @@ -58,7 +209,7 @@ dbus_bus_register_client (DBusConnection *connection, if (!message) { _DBUS_SET_OOM (error); - return NULL; + return FALSE; } reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error); @@ -68,7 +219,7 @@ dbus_bus_register_client (DBusConnection *connection, if (reply == NULL) { _DBUS_ASSERT_ERROR_IS_SET (error); - return NULL; + return FALSE; } if (!dbus_message_get_args (reply, error, @@ -76,10 +227,61 @@ dbus_bus_register_client (DBusConnection *connection, 0)) { _DBUS_ASSERT_ERROR_IS_SET (error); - return NULL; + return FALSE; } + + bd->base_service = name; + + return TRUE; +} + + +/** + * Sets the base service name of the connection. + * Can only be used if you registered with the + * bus manually (i.e. if you did not call + * dbus_bus_register()). Can only be called + * once per connection. + * + * @param connection the connection + * @param the base service name + * @returns #FALSE if not enough memory + */ +dbus_bool_t +dbus_bus_set_base_service (DBusConnection *connection, + const char *base_service) +{ + BusData *bd; + + bd = ensure_bus_data (connection); + if (bd == NULL) + return FALSE; + + _dbus_assert (bd->base_service == NULL); + _dbus_assert (base_service != NULL); + + bd->base_service = _dbus_strdup (base_service); + return bd->base_service != NULL; +} + +/** + * Gets the base service name of the connection. + * Only possible after the connection has been registered + * with the message bus. + * + * @param connection the connection + * @returns the base service name + */ +const char* +dbus_bus_get_base_service (DBusConnection *connection) +{ + BusData *bd; + + bd = ensure_bus_data (connection); + if (bd == NULL) + return NULL; - return name; + return bd->base_service; } /** |