From b34e22726b0e74f7945d37b4ca2a76d74c162277 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 22 Jun 2017 23:31:07 +0100 Subject: [PATCH] bus/containers: Give each instance a list of all its connections Signed-off-by: Simon McVittie https://bugs.freedesktop.org/show_bug.cgi?id=101354 --- bus/containers.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/bus/containers.c b/bus/containers.c index 277c507b..1303fb83 100644 --- a/bus/containers.c +++ b/bus/containers.c @@ -55,6 +55,9 @@ typedef struct BusContainers *containers; DBusServer *server; DBusConnection *creator; + /* List of owned DBusConnection, removed when the DBusConnection is + * removed from the bus */ + DBusList *connections; unsigned long uid; } BusContainerInstance; @@ -218,6 +221,11 @@ bus_container_instance_unref (BusContainerInstance *self) * BusContainerInstance */ _dbus_assert (self->server == NULL); + /* Similarly, as long as there are connections, the BusContainerInstance + * can't be freed, because each connection holds a reference to the + * BusContainerInstance */ + _dbus_assert (self->connections == NULL); + creator_data = dbus_connection_get_data (self->creator, container_creator_data_slot); _dbus_assert (creator_data != NULL); @@ -375,6 +383,11 @@ bus_container_instance_lost_connection (BusContainerInstance *instance, bus_container_instance_ref (instance); dbus_connection_ref (connection); + /* This is O(n), but we don't expect to have many connections per + * container instance. */ + if (_dbus_list_remove (&instance->connections, connection)) + dbus_connection_unref (connection); + dbus_connection_set_data (connection, contained_data_slot, NULL, NULL); dbus_connection_unref (connection); @@ -397,6 +410,16 @@ new_connection_cb (DBusServer *server, return; } + if (_dbus_list_append (&instance->connections, new_connection)) + { + dbus_connection_ref (new_connection); + } + else + { + bus_container_instance_lost_connection (instance, new_connection); + return; + } + /* We don't know how to undo this, so do it last (apart from things that * cannot fail) */ if (!bus_context_add_incoming_connection (instance->context, new_connection)) @@ -817,6 +840,7 @@ bus_containers_remove_connection (BusContainers *self, { #ifdef DBUS_ENABLE_CONTAINERS BusContainerCreatorData *creator_data; + BusContainerInstance *instance; dbus_connection_ref (connection); creator_data = dbus_connection_get_data (connection, @@ -831,7 +855,7 @@ bus_containers_remove_connection (BusContainers *self, iter != NULL; iter = next) { - BusContainerInstance *instance = iter->data; + instance = iter->data; /* Remember where we got to before we do something that might free * iter and instance */ @@ -845,6 +869,18 @@ bus_containers_remove_connection (BusContainers *self, } } + instance = dbus_connection_get_data (connection, contained_data_slot); + + if (instance != NULL) + { + bus_container_instance_ref (instance); + + if (_dbus_list_remove (&instance->connections, connection)) + dbus_connection_unref (connection); + + bus_container_instance_unref (instance); + } + dbus_connection_unref (connection); #endif /* DBUS_ENABLE_CONTAINERS */ } -- 2.13.3