summaryrefslogtreecommitdiff
path: root/dbus/dbus-bus.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-03-16 08:08:21 +0000
committerHavoc Pennington <hp@redhat.com>2003-03-16 08:08:21 +0000
commitce173b29fc1e9432cb5956952afdbe775da12415 (patch)
treebafd96156eba1879568131fe97789e60fd7e6062 /dbus/dbus-bus.c
parentf587ce7845edb0eb01451368d01b5bc86b5904cd (diff)
downloaddbus-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.c218
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;
}
/**